For example, suppose you have a function foo and within foo you call another function baz, where baz has a very large range of customization parameters. If you want to memoize calls to foo with a decorator, you can just pass kwargs for any “pass through” customizations of baz. The memoizing decorator can flatten kwargs out into a tuple along with any positional args, so you get call signature memoization without needing to restrict or list out all possible args of baz. In fact you can make this perfectly generic over the function being memoized so it doesn’t matter if you change baz to bar one day, with a whole new signature.
You can combine this with the inspect module and with functools.wraps to ensure full and complete docstrings and introspected signatures as well, so that putting kwargs all over doesn’t hurt readability, remove info from docstrings or help messages, or make it hard to read.
Interesting use case, thanks for sharing! Out of curiosity, when are some scenarios where it's "critical" to write code this way? I mostly interact with small pytorch / numpy codebases that don't grow large enough for this sort of thing.
Even in hardcore numerical computing this way of working has huge wins over traditional OOP designs or plain flat function designs like C. For example see numba’s jit and autojit decorators that also work this way.
For cases when you want to do it yourself, think of functions that wrap complex matplotlib or seaborn plotting utilities that rely on tons of optional parameters via kwargs. I often find it super helpful to do this when wrapping pandas functions too, which also involve tons of kwargs customization.
FWIW I work professionally in deep learning and other ML. I think scientific computing in Python in particular highlights the importance of this.