What are the uses for **kwargs in Python?
I know you can do an objects.filter on a table and pass in a **kwargs argument. &nbs         
        
kwargs in **kwargs is just variable name. You can very well have **anyVariableNamekwargs stands for "keyword arguments". But I feel they should better be called as "named arguments", as these are simply arguments passed along with names (I dont find any significance to the word "keyword" in the term "keyword arguments". I guess "keyword" usually means words reserved by programming language and hence not to be used by the programmer for variable names. No such thing is happening here in case of kwargs.). So we give names 
param1 and param2 to two parameter values passed to the function as follows: func(param1="val1",param2="val2"), instead of passing only values: func(val1,val2). Thus, I feel they should be appropriately called "arbitrary number of named arguments" as we can specify any number of these parameters (that is, arguments) if func has signature func(**kwargs)So being said that let me explain "named arguments" first and then "arbitrary number of named arguments" kwargs.
Named arguments
Example
def function1(param1,param2="arg2",param3="arg3"):
    print("\n"+str(param1)+" "+str(param2)+" "+str(param3)+"\n")
function1(1)                      #1 arg2 arg3   #1 positional arg
function1(param1=1)               #1 arg2 arg3   #1 named arg
function1(1,param2=2)             #1 2 arg3      #1 positional arg, 1 named arg
function1(param1=1,param2=2)      #1 2 arg3      #2 named args       
function1(param2=2, param1=1)     #1 2 arg3      #2 named args out of order
function1(1, param3=3, param2=2)  #1 2 3         #
#function1()                      #invalid: required argument missing
#function1(param2=2,1)            #invalid: SyntaxError: non-keyword arg after keyword arg
#function1(1,param1=11)           #invalid: TypeError: function1() got multiple values for argument 'param1'
#function1(param4=4)              #invalid: TypeError: function1() got an unexpected keyword argument 'param4'
Arbitrary number of named arguments kwargs
Example
def function2(param1, *tupleParams, param2, param3, **dictionaryParams):
    print("param1: "+ param1)
    print("param2: "+ param2)
    print("param3: "+ param3)
    print("custom tuple params","-"*10)
    for p in tupleParams:
        print(str(p) + ",")
    print("custom named params","-"*10)
    for k,v in dictionaryParams.items():
        print(str(k)+":"+str(v))
function2("arg1",
          "custom param1",
          "custom param2",
          "custom param3",
          param3="arg3",
          param2="arg2", 
          customNamedParam1 = "val1",
          customNamedParam2 = "val2"
          )
# Output
#
#param1: arg1
#param2: arg2
#param3: arg3
#custom tuple params ----------
#custom param1,
#custom param2,
#custom param3,
#custom named params ----------
#customNamedParam2:val2
#customNamedParam1:val1
Passing tuple and dict variables for custom args
To finish it up, let me also note that we can pass
Thus the same above call can be made as follows:
tupleCustomArgs = ("custom param1", "custom param2", "custom param3")
dictCustomNamedArgs = {"customNamedParam1":"val1", "customNamedParam2":"val2"}
function2("arg1",
      *tupleCustomArgs,    #note *
      param3="arg3",
      param2="arg2", 
      **dictCustomNamedArgs     #note **
      )
Finally note * and ** in function calls above. If we omit them, we may get ill results.
Omitting * in tuple args:
function2("arg1",
      tupleCustomArgs,   #omitting *
      param3="arg3",
      param2="arg2", 
      **dictCustomNamedArgs
      )
prints
param1: arg1
param2: arg2
param3: arg3
custom tuple params ----------
('custom param1', 'custom param2', 'custom param3'),
custom named params ----------
customNamedParam2:val2
customNamedParam1:val1
Above tuple ('custom param1', 'custom param2', 'custom param3') is printed as is. 
Omitting dict args:
function2("arg1",
      *tupleCustomArgs,   
      param3="arg3",
      param2="arg2", 
      dictCustomNamedArgs   #omitting **
      )
gives
dictCustomNamedArgs
         ^
SyntaxError: non-keyword arg after keyword arg
                                                                        You can use **kwargs to let your functions take an arbitrary number of keyword arguments ("kwargs" means "keyword arguments"):
>>> def print_keyword_args(**kwargs):
...     # kwargs is a dict of the keyword args passed to the function
...     for key, value in kwargs.iteritems():
...         print "%s = %s" % (key, value)
... 
>>> print_keyword_args(first_name="John", last_name="Doe")
first_name = John
last_name = Doe
You can also use the **kwargs syntax when calling functions by constructing a dictionary of keyword arguments and passing it to your function:
>>> kwargs = {'first_name': 'Bobby', 'last_name': 'Smith'}
>>> print_keyword_args(**kwargs)
first_name = Bobby
last_name = Smith
The Python Tutorial contains a good explanation of how it works, along with some nice examples.
<--Update-->
For people using Python 3, instead of iteritems(), use items()
In Java, you use constructors to overload classes and allow for multiple input parameters. In python, you can use kwargs to provide similar behavior.
java example: https://beginnersbook.com/2013/05/constructor-overloading/
python example:
class Robot():
    # name is an arg and color is a kwarg
    def __init__(self,name, color='red'):
        self.name = name
        self.color = color
red_robot = Robot('Bob')
blue_robot = Robot('Bob', color='blue')
print("I am a {color} robot named {name}.".format(color=red_robot.color, name=red_robot.name))
print("I am a {color} robot named {name}.".format(color=blue_robot.color, name=blue_robot.name))
>>> I am a red robot named Bob.
>>> I am a blue robot named Bob.
just another way to think about it.
Motif: *args and **kwargs serves as a placeholder for the arguments that need to be passed to a function call
using *args and **kwargs to call a function  
def args_kwargs_test(arg1, arg2, arg3):
    print "arg1:", arg1
    print "arg2:", arg2
    print "arg3:", arg3
Now we'll use *args to call the above defined function  
#args can either be a "list" or "tuple"
>>> args = ("two", 3, 5)  
>>> args_kwargs_test(*args)
arg1: two
arg2: 3
arg3: 5
Now, using **kwargs to call the same function
#keyword argument "kwargs" has to be a dictionary
>>> kwargs = {"arg3":3, "arg2":'two', "arg1":5}
>>> args_kwargs_test(**kwargs)
arg1: 5
arg2: two
arg3: 3  
Bottomline : *args has no intelligence, it simply interpolates the passed args to the parameters(in left-to-right order) while **kwargs behaves intelligently by placing the appropriate value @ the required place
Here's a simple function that serves to explain the usage:
def print_wrap(arg1, *args, **kwargs):
    print(arg1)
    print(args)
    print(kwargs)
    print(arg1, *args, **kwargs)
Any arguments that are not specified in the function definition will be put in the args list, or the kwargs list, depending on whether they are keyword arguments or not:
>>> print_wrap('one', 'two', 'three', end='blah', sep='--')
one
('two', 'three')
{'end': 'blah', 'sep': '--'}
one--two--threeblah
If you add a keyword argument that never gets passed to a function, an error will be raised:
>>> print_wrap('blah', dead_arg='anything')
TypeError: 'dead_arg' is an invalid keyword argument for this function
                                                                        ** unpacks dictionaries.
This
func(a=1, b=2, c=3)
is the same as
args = {'a': 1, 'b': 2, 'c':3}
func(**args)
It's useful if you have to construct parameters:
args = {'name': person.name}
if hasattr(person, "address"):
    args["address"] = person.address
func(**args)  # either expanded to func(name=person.name) or
              #                    func(name=person.name, address=person.address)
def setstyle(**styles):
    for key, value in styles.iteritems():      # styles is a regular dictionary
        setattr(someobject, key, value)
This lets you use the function like this:
setstyle(color="red", bold=False)