*args and **kwargs allow us to pass multiple arguments and multiple keyword arguments, respectively, to a function. But what is idea behind it and the advantages?
Whenever you define a function, it can only take the number of arguments as defined initially. However, when you define it with *args, it can take any number of arguments when the function is called. Similarly, any number of keyword arguments can be passed when **kwargs is defined.
The * operator essentially unpacks the list and the *args parameter becomes an iterable object. Similarly, ** unpacks a dictionary and hence **kwargs becomes an iterable keyword argument object.
One of its many useful applications in ML is while Hyperparameter Tuning. When we perform a grid search operation, we get the best parameters (best_params) in form of a dictionary.
Now one way would be to copy all these best parameters and pass into the model object. However, with **kwargs, this dictionary can be straightaway passed to the model as **best_params keyword argument !
rf = RandomForestRegressor(**best_params)