diff --git a/django/template/base.py b/django/template/base.py
index b96e446..8713f48 100644
--- a/django/template/base.py
+++ b/django/template/base.py
@@ -799,18 +799,26 @@ class VariableNode(Node):
             return ''
         return _render_value_in_context(output, context)
 
-def generic_tag_compiler(params, defaults, name, node_class, parser, token):
-    "Returns a template.Node subclass."
-    bits = token.split_contents()[1:]
+def generic_tag_syntax_check(bits, params, defaults, name, varargs):
     bmax = len(params)
     def_len = defaults and len(defaults) or 0
     bmin = bmax - def_len
-    if(len(bits) < bmin or len(bits) > bmax):
-        if bmin == bmax:
-            message = "%s takes %s arguments" % (name, bmin)
-        else:
-            message = "%s takes between %s and %s arguments" % (name, bmin, bmax)
-        raise TemplateSyntaxError(message)
+    if varargs is None:
+        if(len(bits) < bmin or len(bits) > bmax):
+            if bmin == bmax:
+                message = "'%s' tag takes %s argument(s)" % (name, bmin)
+            else:
+                message = "'%s' tag takes between %s and %s arguments" % (name, bmin, bmax)
+            raise TemplateSyntaxError(message)
+    else:
+        if(len(bits) < bmin):
+            message = "'%s' tag takes at least %s argument(s)" % (name, bmin)
+            raise TemplateSyntaxError(message)
+
+def generic_tag_compiler(parser, token, params, defaults, name, node_class, varargs=None):
+    "Returns a template.Node subclass."
+    bits = token.split_contents()[1:]
+    generic_tag_syntax_check(bits, params, defaults, name, varargs)
     return node_class(bits)
 
 class Library(object):
@@ -868,7 +876,7 @@ class Library(object):
 
     def simple_tag(self, func=None, takes_context=None, name=None):
         def dec(func):
-            params, xx, xxx, defaults = getargspec(func)
+            params, varargs, xxx, defaults = getargspec(func)
             if takes_context:
                 if params[0] == 'context':
                     params = params[1:]
@@ -888,7 +896,7 @@ class Library(object):
                     return func(*func_args)
 
             function_name = name or getattr(func, '_decorated_function', func).__name__
-            compile_func = partial(generic_tag_compiler, params, defaults, function_name, SimpleNode)
+            compile_func = partial(generic_tag_compiler, params=params, defaults=defaults, name=function_name, node_class=SimpleNode, varargs=varargs)
             compile_func.__doc__ = func.__doc__
             self.tag(function_name, compile_func)
             return func
@@ -904,7 +912,7 @@ class Library(object):
 
     def assignment_tag(self, func=None, takes_context=None, name=None):
         def dec(func):
-            params, xx, xxx, defaults = getargspec(func)
+            params, varargs, xxx, defaults = getargspec(func)
             if takes_context:
                 if params[0] == 'context':
                     params = params[1:]
@@ -925,31 +933,19 @@ class Library(object):
                     context[self.target_var] = func(*func_args)
                     return ''
 
+            function_name = name or getattr(func, '_decorated_function', func).__name__
+
             def compile_func(parser, token):
-                bits = token.split_contents()
-                tag_name = bits[0]
-                bits = bits[1:]
-                params_max = len(params)
-                defaults_length = defaults and len(defaults) or 0
-                params_min = params_max - defaults_length
+                bits = token.split_contents()[1:]
                 if (len(bits) < 2 or bits[-2] != 'as'):
                     raise TemplateSyntaxError(
                         "'%s' tag takes at least 2 arguments and the "
-                        "second last argument must be 'as'" % tag_name)
-                params_vars = bits[:-2]
+                        "second last argument must be 'as'" % function_name)
                 target_var = bits[-1]
-                if (len(params_vars) < params_min or
-                        len(params_vars) > params_max):
-                    if params_min == params_max:
-                        raise TemplateSyntaxError(
-                            "%s takes %s arguments" % (tag_name, params_min))
-                    else:
-                        raise TemplateSyntaxError(
-                            "%s takes between %s and %s arguments"
-                            % (tag_name, params_min, params_max))
-                return AssignmentNode(params_vars, target_var)
+                args = bits[:-2]
+                generic_tag_syntax_check(args, params, defaults, function_name, varargs)
+                return AssignmentNode(args, target_var)
 
-            function_name = name or getattr(func, '_decorated_function', func).__name__
             compile_func.__doc__ = func.__doc__
             self.tag(function_name, compile_func)
             return func
@@ -965,7 +961,7 @@ class Library(object):
 
     def inclusion_tag(self, file_name, context_class=Context, takes_context=False, name=None):
         def dec(func):
-            params, xx, xxx, defaults = getargspec(func)
+            params, varargs, xxx, defaults = getargspec(func)
             if takes_context:
                 if params[0] == 'context':
                     params = params[1:]
@@ -1008,7 +1004,7 @@ class Library(object):
                     return self.nodelist.render(new_context)
 
             function_name = name or getattr(func, '_decorated_function', func).__name__
-            compile_func = partial(generic_tag_compiler, params, defaults, function_name, InclusionNode)
+            compile_func = partial(generic_tag_compiler, params=params, defaults=defaults, name=function_name, node_class=InclusionNode, varargs=varargs)
             compile_func.__doc__ = func.__doc__
             self.tag(function_name, compile_func)
             return func
diff --git a/docs/howto/custom-template-tags.txt b/docs/howto/custom-template-tags.txt
index 1e22684..c970022 100644
--- a/docs/howto/custom-template-tags.txt
+++ b/docs/howto/custom-template-tags.txt
@@ -697,6 +697,14 @@ If you need to rename your tag, you can provide a custom name for it::
     def some_function(value):
         return value - 1
 
+.. versionadded:: 1.4
+
+Simple tags can also take variable arguments. For example::
+
+    @register.simple_tag
+    def comma_separated(*args):
+        return ', '.join([unicode(arg) for arg in args])
+
 .. _howto-custom-template-tags-assignment-tags:
 
 Assignment tags
@@ -883,6 +891,12 @@ The ``takes_context`` parameter defaults to ``False``. When it's set to *True*,
 the tag is passed the context object, as in this example. That's the only
 difference between this case and the previous ``inclusion_tag`` example.
 
+.. versionadded:: 1.4
+
+Like :ref:`simple tags <howto-custom-template-tags-simple-tags>` and
+:ref:`assignment tags <howto-custom-template-tags-assignment-tags>`, inclusion
+tags can accept a variable number of arguments.
+
 Setting a variable in the context
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
diff --git a/docs/releases/1.4.txt b/docs/releases/1.4.txt
index 7cc3fb1..1e50a70 100644
--- a/docs/releases/1.4.txt
+++ b/docs/releases/1.4.txt
@@ -189,6 +189,10 @@ Django 1.4 also includes several smaller improvements worth noting:
 
 * Customizable names for :meth:`~django.template.Library.simple_tag`.
 
+* Variable ``*args`` support for
+  :meth:`~django.template.Library.simple_tag` and
+  :meth:`~django.template.Library.inclusion_tag`.
+
 * In the documentation, a helpful :doc:`security overview </topics/security>`
   page.
 
diff --git a/tests/regressiontests/templates/custom.py b/tests/regressiontests/templates/custom.py
index 74c39ab..c33eb4f 100644
--- a/tests/regressiontests/templates/custom.py
+++ b/tests/regressiontests/templates/custom.py
@@ -37,6 +37,27 @@ class CustomTagTests(TestCase):
         t = template.Template('{% load custom %}{% params_and_context 37 %}')
         self.assertEqual(t.render(c), u'params_and_context - Expected result (context value: 42): 37')
 
+        t = template.Template('{% load custom %}{% simple_two_params 37 42 %}')
+        self.assertEqual(t.render(c), u'simple_two_params - Expected result: 37, 42')
+
+        t = template.Template('{% load custom %}{% simple_one_default 37 %}')
+        self.assertEqual(t.render(c), u'simple_one_default - Expected result: 37, hi')
+
+        t = template.Template('{% load custom %}{% simple_one_default 37 42 %}')
+        self.assertEqual(t.render(c), u'simple_one_default - Expected result: 37, 42')
+
+        t = template.Template('{% load custom %}{% simple_unlimited_params 37 %}')
+        self.assertEqual(t.render(c), u'simple_unlimited_params - Expected result: 37, hi')
+
+        t = template.Template('{% load custom %}{% simple_unlimited_params 37 42 56 89 %}')
+        self.assertEqual(t.render(c), u'simple_unlimited_params - Expected result: 37, 42, 56, 89')
+
+        t = template.Template('{% load custom %}{% simple_only_unlimited_params %}')
+        self.assertEqual(t.render(c), u'simple_only_unlimited_params - Expected result: ')
+
+        t = template.Template('{% load custom %}{% simple_only_unlimited_params 37 42 56 89 %}')
+        self.assertEqual(t.render(c), u'simple_only_unlimited_params - Expected result: 37, 42, 56, 89')
+
     def test_simple_tag_registration(self):
         # Test that the decorators preserve the decorated function's docstring, name and attributes.
         self.verify_tag(custom.no_params, 'no_params')
@@ -73,6 +94,43 @@ class CustomTagTests(TestCase):
         t = template.Template('{% load custom %}{% inclusion_params_and_context 37 %}')
         self.assertEqual(t.render(c), u'inclusion_params_and_context - Expected result (context value: 42): 37\n')
 
+        t = template.Template('{% load custom %}{% inclusion_two_params 37 42 %}')
+        self.assertEqual(t.render(c), u'inclusion_two_params - Expected result: 37, 42\n')
+
+        t = template.Template('{% load custom %}{% inclusion_one_default 37 %}')
+        self.assertEqual(t.render(c), u'inclusion_one_default - Expected result: 37, hi\n')
+
+        t = template.Template('{% load custom %}{% inclusion_one_default 37 42 %}')
+        self.assertEqual(t.render(c), u'inclusion_one_default - Expected result: 37, 42\n')
+
+        t = template.Template('{% load custom %}{% inclusion_unlimited_params 37 %}')
+        self.assertEqual(t.render(c), u'inclusion_unlimited_params - Expected result: 37, hi\n')
+
+        t = template.Template('{% load custom %}{% inclusion_unlimited_params 37 42 56 89 %}')
+        self.assertEqual(t.render(c), u'inclusion_unlimited_params - Expected result: 37, 42, 56, 89\n')
+
+        t = template.Template('{% load custom %}{% inclusion_only_unlimited_params %}')
+        self.assertEqual(t.render(c), u'inclusion_only_unlimited_params - Expected result: \n')
+
+        t = template.Template('{% load custom %}{% inclusion_only_unlimited_params 37 42 56 89 %}')
+        self.assertEqual(t.render(c), u'inclusion_only_unlimited_params - Expected result: 37, 42, 56, 89\n')
+
+        self.assertRaisesRegexp(template.TemplateSyntaxError,
+            "'inclusion_two_params' tag takes 2 argument\(s\)",
+            template.Template, '{% load custom %}{% inclusion_two_params 37 42 56 %}')
+
+        self.assertRaisesRegexp(template.TemplateSyntaxError,
+            "'inclusion_one_default' tag takes between 1 and 2 arguments",
+            template.Template, '{% load custom %}{% inclusion_one_default 37 42 56 %}')
+
+        self.assertRaisesRegexp(template.TemplateSyntaxError,
+            "'inclusion_one_default' tag takes between 1 and 2 arguments",
+            template.Template, '{% load custom %}{% inclusion_one_default %}')
+
+        self.assertRaisesRegexp(template.TemplateSyntaxError,
+            "'inclusion_unlimited_params' tag takes at least 1 argument\(s\)",
+            template.Template, '{% load custom %}{% inclusion_unlimited_params %}')
+
     def test_inclusion_tags_from_template(self):
         c = template.Context({'value': 42})
 
@@ -91,6 +149,27 @@ class CustomTagTests(TestCase):
         t = template.Template('{% load custom %}{% inclusion_params_and_context_from_template 37 %}')
         self.assertEqual(t.render(c), u'inclusion_params_and_context_from_template - Expected result (context value: 42): 37\n')
 
+        t = template.Template('{% load custom %}{% inclusion_two_params_from_template 37 42 %}')
+        self.assertEqual(t.render(c), u'inclusion_two_params_from_template - Expected result: 37, 42\n')
+
+        t = template.Template('{% load custom %}{% inclusion_one_default_from_template 37 %}')
+        self.assertEqual(t.render(c), u'inclusion_one_default_from_template - Expected result: 37, hi\n')
+
+        t = template.Template('{% load custom %}{% inclusion_one_default_from_template 37 42 %}')
+        self.assertEqual(t.render(c), u'inclusion_one_default_from_template - Expected result: 37, 42\n')
+
+        t = template.Template('{% load custom %}{% inclusion_unlimited_params_from_template 37 %}')
+        self.assertEqual(t.render(c), u'inclusion_unlimited_params_from_template - Expected result: 37, hi\n')
+
+        t = template.Template('{% load custom %}{% inclusion_unlimited_params_from_template 37 42 56 89 %}')
+        self.assertEqual(t.render(c), u'inclusion_unlimited_params_from_template - Expected result: 37, 42, 56, 89\n')
+
+        t = template.Template('{% load custom %}{% inclusion_only_unlimited_params_from_template %}')
+        self.assertEqual(t.render(c), u'inclusion_only_unlimited_params_from_template - Expected result: \n')
+
+        t = template.Template('{% load custom %}{% inclusion_only_unlimited_params_from_template 37 42 56 89 %}')
+        self.assertEqual(t.render(c), u'inclusion_only_unlimited_params_from_template - Expected result: 37, 42, 56, 89\n')
+
     def test_inclusion_tag_registration(self):
         # Test that the decorators preserve the decorated function's docstring, name and attributes.
         self.verify_tag(custom.inclusion_no_params, 'inclusion_no_params')
@@ -98,6 +177,10 @@ class CustomTagTests(TestCase):
         self.verify_tag(custom.inclusion_explicit_no_context, 'inclusion_explicit_no_context')
         self.verify_tag(custom.inclusion_no_params_with_context, 'inclusion_no_params_with_context')
         self.verify_tag(custom.inclusion_params_and_context, 'inclusion_params_and_context')
+        self.verify_tag(custom.inclusion_two_params, 'inclusion_two_params')
+        self.verify_tag(custom.inclusion_one_default, 'inclusion_one_default')
+        self.verify_tag(custom.inclusion_unlimited_params, 'inclusion_unlimited_params')
+        self.verify_tag(custom.inclusion_only_unlimited_params, 'inclusion_only_unlimited_params')
 
     def test_15070_current_app(self):
         """
@@ -141,6 +224,27 @@ class CustomTagTests(TestCase):
         t = template.Template('{% load custom %}{% assignment_params_and_context 37 as var %}The result is: {{ var }}')
         self.assertEqual(t.render(c), u'The result is: assignment_params_and_context - Expected result (context value: 42): 37')
 
+        t = template.Template('{% load custom %}{% assignment_two_params 37 42 as var %}The result is: {{ var }}')
+        self.assertEqual(t.render(c), u'The result is: assignment_two_params - Expected result: 37, 42')
+
+        t = template.Template('{% load custom %}{% assignment_one_default 37 as var %}The result is: {{ var }}')
+        self.assertEqual(t.render(c), u'The result is: assignment_one_default - Expected result: 37, hi')
+
+        t = template.Template('{% load custom %}{% assignment_one_default 37 42 as var %}The result is: {{ var }}')
+        self.assertEqual(t.render(c), u'The result is: assignment_one_default - Expected result: 37, 42')
+
+        t = template.Template('{% load custom %}{% assignment_unlimited_params 37 as var %}The result is: {{ var }}')
+        self.assertEqual(t.render(c), u'The result is: assignment_unlimited_params - Expected result: 37, hi')
+
+        t = template.Template('{% load custom %}{% assignment_unlimited_params 37 42 56 89 as var %}The result is: {{ var }}')
+        self.assertEqual(t.render(c), u'The result is: assignment_unlimited_params - Expected result: 37, 42, 56, 89')
+
+        t = template.Template('{% load custom %}{% assignment_only_unlimited_params as var %}The result is: {{ var }}')
+        self.assertEqual(t.render(c), u'The result is: assignment_only_unlimited_params - Expected result: ')
+
+        t = template.Template('{% load custom %}{% assignment_only_unlimited_params 37 42 56 89 as var %}The result is: {{ var }}')
+        self.assertEqual(t.render(c), u'The result is: assignment_only_unlimited_params - Expected result: 37, 42, 56, 89')
+
         self.assertRaisesRegexp(template.TemplateSyntaxError,
             "'assignment_one_param' tag takes at least 2 arguments and the second last argument must be 'as'",
             template.Template, '{% load custom %}{% assignment_one_param 37 %}The result is: {{ var }}')
@@ -153,6 +257,22 @@ class CustomTagTests(TestCase):
             "'assignment_one_param' tag takes at least 2 arguments and the second last argument must be 'as'",
             template.Template, '{% load custom %}{% assignment_one_param 37 ass var %}The result is: {{ var }}')
 
+        self.assertRaisesRegexp(template.TemplateSyntaxError,
+            "'assignment_two_params' tag takes 2 argument\(s\)",
+            template.Template, '{% load custom %}{% assignment_two_params 37 42 56 as var %}The result is: {{ var }}')
+
+        self.assertRaisesRegexp(template.TemplateSyntaxError,
+            "'assignment_one_default' tag takes between 1 and 2 arguments",
+            template.Template, '{% load custom %}{% assignment_one_default 37 42 56 as var %}The result is: {{ var }}')
+
+        self.assertRaisesRegexp(template.TemplateSyntaxError,
+            "'assignment_one_default' tag takes between 1 and 2 arguments",
+            template.Template, '{% load custom %}{% assignment_one_default as var %}The result is: {{ var }}')
+
+        self.assertRaisesRegexp(template.TemplateSyntaxError,
+            "'assignment_unlimited_params' tag takes at least 1 argument\(s\)",
+            template.Template, '{% load custom %}{% assignment_unlimited_params as var %}The result is: {{ var }}')
+
     def test_assignment_tag_registration(self):
         # Test that the decorators preserve the decorated function's docstring, name and attributes.
         self.verify_tag(custom.assignment_no_params, 'assignment_no_params')
@@ -160,6 +280,10 @@ class CustomTagTests(TestCase):
         self.verify_tag(custom.assignment_explicit_no_context, 'assignment_explicit_no_context')
         self.verify_tag(custom.assignment_no_params_with_context, 'assignment_no_params_with_context')
         self.verify_tag(custom.assignment_params_and_context, 'assignment_params_and_context')
+        self.verify_tag(custom.assignment_one_default, 'assignment_one_default')
+        self.verify_tag(custom.assignment_two_params, 'assignment_two_params')
+        self.verify_tag(custom.assignment_unlimited_params, 'assignment_unlimited_params')
+        self.verify_tag(custom.assignment_only_unlimited_params, 'assignment_only_unlimited_params')
 
     def test_assignment_tag_missing_context(self):
         # That the 'context' parameter must be present when takes_context is True
diff --git a/tests/regressiontests/templates/templatetags/custom.py b/tests/regressiontests/templates/templatetags/custom.py
index dfa4171..0ed7f27 100644
--- a/tests/regressiontests/templates/templatetags/custom.py
+++ b/tests/regressiontests/templates/templatetags/custom.py
@@ -40,6 +40,30 @@ def params_and_context(context, arg):
     return "params_and_context - Expected result (context value: %s): %s" % (context['value'], arg)
 params_and_context.anything = "Expected params_and_context __dict__"
 
+@register.simple_tag
+def simple_two_params(one, two):
+    """Expected simple_two_params __doc__"""
+    return "simple_two_params - Expected result: %s, %s" % (one, two)
+simple_two_params.anything = "Expected simple_two_params __dict__"
+
+@register.simple_tag
+def simple_one_default(one, two='hi'):
+    """Expected simple_one_default __doc__"""
+    return "simple_one_default - Expected result: %s, %s" % (one, two)
+simple_one_default.anything = "Expected simple_one_default __dict__"
+
+@register.simple_tag
+def simple_unlimited_params(one, two='hi', *args):
+    """Expected simple_unlimited_params __doc__"""
+    return "simple_unlimited_params - Expected result: %s" % (', '.join([unicode(arg) for arg in [one, two] + list(args)]))
+simple_unlimited_params.anything = "Expected simple_unlimited_params __dict__"
+
+@register.simple_tag
+def simple_only_unlimited_params(*args):
+    """Expected simple_only_unlimited_params __doc__"""
+    return "simple_only_unlimited_params - Expected result: %s" % ', '.join([unicode(arg) for arg in args])
+simple_only_unlimited_params.anything = "Expected simple_only_unlimited_params __dict__"
+
 @register.inclusion_tag('inclusion.html')
 def inclusion_no_params():
     """Expected inclusion_no_params __doc__"""
@@ -100,6 +124,54 @@ def inclusion_params_and_context_from_template(context, arg):
     return {"result" : "inclusion_params_and_context_from_template - Expected result (context value: %s): %s" % (context['value'], arg)}
 inclusion_params_and_context_from_template.anything = "Expected inclusion_params_and_context_from_template __dict__"
 
+@register.inclusion_tag('inclusion.html')
+def inclusion_two_params(one, two):
+    """Expected inclusion_two_params __doc__"""
+    return {"result": "inclusion_two_params - Expected result: %s, %s" % (one, two)}
+inclusion_two_params.anything = "Expected inclusion_two_params __dict__"
+
+@register.inclusion_tag(get_template('inclusion.html'))
+def inclusion_two_params_from_template(one, two):
+    """Expected inclusion_two_params_from_template __doc__"""
+    return {"result": "inclusion_two_params_from_template - Expected result: %s, %s" % (one, two)}
+inclusion_two_params_from_template.anything = "Expected inclusion_two_params_from_template __dict__"
+
+@register.inclusion_tag('inclusion.html')
+def inclusion_one_default(one, two='hi'):
+    """Expected inclusion_one_default __doc__"""
+    return {"result": "inclusion_one_default - Expected result: %s, %s" % (one, two)}
+inclusion_one_default.anything = "Expected inclusion_one_default __dict__"
+
+@register.inclusion_tag(get_template('inclusion.html'))
+def inclusion_one_default_from_template(one, two='hi'):
+    """Expected inclusion_one_default_from_template __doc__"""
+    return {"result": "inclusion_one_default_from_template - Expected result: %s, %s" % (one, two)}
+inclusion_one_default_from_template.anything = "Expected inclusion_one_default_from_template __dict__"
+
+@register.inclusion_tag('inclusion.html')
+def inclusion_unlimited_params(one, two='hi', *args):
+    """Expected inclusion_unlimited_params __doc__"""
+    return {"result": "inclusion_unlimited_params - Expected result: %s" % (', '.join([unicode(arg) for arg in [one, two] + list(args)]))}
+inclusion_unlimited_params.anything = "Expected inclusion_unlimited_params __dict__"
+
+@register.inclusion_tag(get_template('inclusion.html'))
+def inclusion_unlimited_params_from_template(one, two='hi', *args):
+    """Expected inclusion_unlimited_params_from_template __doc__"""
+    return {"result": "inclusion_unlimited_params_from_template - Expected result: %s" % (', '.join([unicode(arg) for arg in [one, two] + list(args)]))}
+inclusion_unlimited_params_from_template.anything = "Expected inclusion_unlimited_params_from_template __dict__"
+
+@register.inclusion_tag('inclusion.html')
+def inclusion_only_unlimited_params(*args):
+    """Expected inclusion_only_unlimited_params __doc__"""
+    return {"result": "inclusion_only_unlimited_params - Expected result: %s" % (', '.join([unicode(arg) for arg in args]))}
+inclusion_only_unlimited_params.anything = "Expected inclusion_only_unlimited_params __dict__"
+
+@register.inclusion_tag(get_template('inclusion.html'))
+def inclusion_only_unlimited_params_from_template(*args):
+    """Expected inclusion_only_unlimited_params_from_template __doc__"""
+    return {"result": "inclusion_only_unlimited_params_from_template - Expected result: %s" % (', '.join([unicode(arg) for arg in args]))}
+inclusion_only_unlimited_params_from_template.anything = "Expected inclusion_only_unlimited_params_from_template __dict__"
+
 @register.simple_tag(takes_context=True)
 def current_app(context):
     return "%s" % context.current_app
@@ -146,6 +218,30 @@ def assignment_params_and_context(context, arg):
     return "assignment_params_and_context - Expected result (context value: %s): %s" % (context['value'], arg)
 assignment_params_and_context.anything = "Expected assignment_params_and_context __dict__"
 
+@register.assignment_tag
+def assignment_two_params(one, two):
+    """Expected assignment_two_params __doc__"""
+    return "assignment_two_params - Expected result: %s, %s" % (one, two)
+assignment_two_params.anything = "Expected assignment_two_params __dict__"
+
+@register.assignment_tag
+def assignment_one_default(one, two='hi'):
+    """Expected assignment_one_default __doc__"""
+    return "assignment_one_default - Expected result: %s, %s" % (one, two)
+assignment_one_default.anything = "Expected assignment_one_default __dict__"
+
+@register.assignment_tag
+def assignment_unlimited_params(one, two='hi', *args):
+    """Expected assignment_unlimited_params __doc__"""
+    return "assignment_unlimited_params - Expected result: %s" % (', '.join([unicode(arg) for arg in [one, two] + list(args)]))
+assignment_unlimited_params.anything = "Expected assignment_unlimited_params __dict__"
+
+@register.assignment_tag
+def assignment_only_unlimited_params(*args):
+    """Expected assignment_only_unlimited_params __doc__"""
+    return "assignment_only_unlimited_params - Expected result: %s" % ', '.join([unicode(arg) for arg in args])
+assignment_only_unlimited_params.anything = "Expected assignment_only_unlimited_params __dict__"
+
 register.simple_tag(lambda x: x - 1, name='minusone')
 
 @register.simple_tag(name='minustwo')
