diff --git a/kwant/_system.pyx b/kwant/_system.pyx
index d297dbc1961b5b49e8c1af34f283d33f29746aea..45e0da438e6b9a7322307331982ea76d8cf272c7 100644
--- a/kwant/_system.pyx
+++ b/kwant/_system.pyx
@@ -16,6 +16,7 @@ import types
 from .graph.core cimport CGraph, gintArraySlice
 from .graph.defs cimport gint
 from .graph.defs import gint_dtype
+from ._common import deprecate_args
 
 msg = ('Hopping from site {0} to site {1} does not match the '
        'dimensions of onsite Hamiltonians of these sites.')
@@ -253,6 +254,7 @@ def _check_parameters_match(expected_parameters, params):
         raise TypeError(''.join(msg))
 
 
+@deprecate_args
 @cython.binding(True)
 @cython.embedsignature(True)
 def hamiltonian_submatrix(self, args=(), to_sites=None, from_sites=None,
diff --git a/kwant/builder.py b/kwant/builder.py
index c804c3a8f07e9617f0e953f7036c81f467fbb23c..5b89731ae4c14f1c9d585c65b78a40d4f1110310 100644
--- a/kwant/builder.py
+++ b/kwant/builder.py
@@ -22,7 +22,7 @@ from .linalg import lll
 from .operator import Density
 from .physics import DiscreteSymmetry
 from ._common import (ensure_isinstance, get_parameters, reraise_warnings,
-                      interleave)
+                      interleave, deprecate_args)
 
 
 __all__ = ['Builder', 'Site', 'SiteFamily', 'SimpleSiteFamily', 'Symmetry',
@@ -617,6 +617,7 @@ def _ensure_signature(func):
         return func
 
     # function conforming to old API: needs wrapping
+    @deprecate_args
     def wrapper(energy, args=(), *, params=None):
         return func(energy, args)
 
@@ -647,6 +648,7 @@ class SelfEnergyLead(Lead):
         """Trivial finalization: the object is returned itself."""
         return self
 
+    @deprecate_args
     def selfenergy(self, energy, args=(), *, params=None):
         return self.selfenergy_func(energy, args, params=params)
 
@@ -677,9 +679,11 @@ class ModesLead(Lead):
         """Trivial finalization: the object is returned itself."""
         return self
 
+    @deprecate_args
     def modes(self, energy, args=(), *, params=None):
         return self.modes_func(energy, args, params=params)
 
+    @deprecate_args
     def selfenergy(self, energy, args=(), *, params=None):
         stabilized = self.modes(energy, args, params=params)[1]
         return stabilized.selfenergy()
@@ -1894,6 +1898,7 @@ class _FinalizedBuilderMixin:
                 value = herm_conj(value)
         return value
 
+    @deprecate_args
     def discrete_symmetry(self, args=(), *, params=None):
         if self._cons_law is not None:
             eigvals, eigvecs = self._cons_law
diff --git a/kwant/operator.pyx b/kwant/operator.pyx
index 0b1a8e279f5b3a95609e61dd23ddb183474889c5..002eb8b66e188aa95a44b3e5c6248187dfaa6319 100644
--- a/kwant/operator.pyx
+++ b/kwant/operator.pyx
@@ -24,7 +24,7 @@ from .graph.core cimport EdgeIterator
 from .graph.defs cimport gint
 from .graph.defs import gint_dtype
 from .system import InfiniteSystem
-from ._common import UserCodeError, get_parameters
+from ._common import UserCodeError, get_parameters, deprecate_args
 
 
 ################ Generic Utility functions
@@ -499,7 +499,7 @@ cdef class _LocalOperator:
         args : tuple, optional
             The arguments to pass to the system. Used to evaluate
             the ``onsite`` elements and, possibly, the system Hamiltonian.
-            Mutually exclusive with 'params'.
+            Deprecated in favor of 'params' (and mutually exclusive with it).
         params : dict, optional
             Dictionary of parameter names and their values. Mutually exclusive
             with 'args'.
@@ -514,6 +514,11 @@ cdef class _LocalOperator:
             raise ValueError("Extra arguments are already bound to this "
                              "operator. You should call this operator "
                              "providing neither 'args' nor 'params'.")
+        if args:
+            # deprecate_args does not play nicely with methods of cdef classes,
+            # when used as a decorator, so we manually raise the
+            # deprecation warning here.
+            deprecate_args()
         if args and params:
             raise TypeError("'args' and 'params' are mutually exclusive.")
         if bra is None:
@@ -555,7 +560,8 @@ cdef class _LocalOperator:
             Wavefunctions defined over all the orbitals of the system.
         args : tuple
             The extra arguments to the Hamiltonian value functions and
-            the operator ``onsite`` function. Mutually exclusive with 'params'.
+            the operator ``onsite`` function.
+            Deprecated in favor of 'params' (and mutually exclusive with it).
         params : dict, optional
             Dictionary of parameter names and their values. Mutually exclusive
             with 'args'.
@@ -568,6 +574,11 @@ cdef class _LocalOperator:
             raise ValueError("Extra arguments are already bound to this "
                              "operator. You should call this operator "
                              "providing neither 'args' nor 'params'.")
+        if args:
+            # deprecate_args does not play nicely with methods of cdef classes,
+            # when used as a decorator, so we manually raise the
+            # deprecation warning here.
+            deprecate_args()
         if args and params:
             raise TypeError("'args' and 'params' are mutually exclusive.")
 
@@ -588,7 +599,15 @@ cdef class _LocalOperator:
 
         Returns a copy of this operator that does not need to be passed extra
         arguments when subsequently called or when using the ``act`` method.
+
+        Providing positional arguments via 'args' is deprecated,
+        instead provide named parameters as a dictionary via 'params'.
         """
+        if args:
+            # deprecate_args does not play nicely with methods of cdef classes,
+            # when used as a decorator, so we manually raise the
+            # deprecation warning here.
+            deprecate_args()
         if args and params:
             raise TypeError("'args' and 'params' are mutually exclusive.")
         # generic creation of new instance
@@ -621,7 +640,8 @@ cdef class _LocalOperator:
             If `op` is `ACT` then `bra` is None.
         args : tuple
             The extra arguments to the Hamiltonian value functions and
-            the operator ``onsite`` function. Mutually exclusive with 'params'.
+            the operator ``onsite`` function.
+            Deprecated in favor of 'params' (and mutually exclusive with it).
         op : operation
             The operation to perform.
             `MAT_ELS`: calculate matrix elements between `bra` and `ket`
@@ -786,7 +806,11 @@ cdef class Density(_LocalOperator):
     @cython.cdivision(True)
     @cython.embedsignature
     def tocoo(self, args=(), *, params=None):
-        """Convert the operator to coordinate format sparse matrix."""
+        """Convert the operator to coordinate format sparse matrix.
+
+        Providing positional arguments via 'args' is deprecated,
+        instead provide named parameters as a dictionary via 'params'.
+        """
         cdef int blk, blk_size, n_blocks, n, k = 0
         cdef int [:, :] offsets, shapes
         cdef int [:] row, col
@@ -794,6 +818,11 @@ cdef class Density(_LocalOperator):
            raise ValueError("Extra arguments are already bound to this "
                             "operator. You should call this operator "
                             "providing neither 'args' nor 'params'.")
+        if args:
+            # deprecate_args does not play nicely with methods of cdef classes,
+            # when used as a decorator, so we manually raise the
+            # deprecation warning here.
+            deprecate_args()
         if args and params:
             raise TypeError("'args' and 'params' are mutually exclusive.")
 
@@ -887,6 +916,9 @@ cdef class Current(_LocalOperator):
 
         Returns a copy of this operator that does not need to be passed extra
         arguments when subsequently called or when using the ``act`` method.
+
+        Providing positional arguments via 'args' is deprecated,
+        instead provide named parameters as a dictionary via 'params'.
         """
         q = super().bind(args, params=params)
         q._bound_hamiltonian = self._eval_hamiltonian(args, params)
@@ -1012,6 +1044,9 @@ cdef class Source(_LocalOperator):
 
         Returns a copy of this operator that does not need to be passed extra
         arguments when subsequently called or when using the ``act`` method.
+
+        Providing positional arguments via 'args' is deprecated,
+        instead provide named parameters as a dictionary via 'params'.
         """
         q = super().bind(args, params=params)
         q._bound_hamiltonian = self._eval_hamiltonian(args, params)
diff --git a/kwant/physics/dispersion.py b/kwant/physics/dispersion.py
index 5c98bf2618536fea4262df0ef8476dcc9181e721..f35a7781695b16902a4d0ec781e2656bebcfe073 100644
--- a/kwant/physics/dispersion.py
+++ b/kwant/physics/dispersion.py
@@ -11,7 +11,7 @@
 import math
 import numpy as np
 from .. import system
-from .._common import ensure_isinstance
+from .._common import ensure_isinstance, deprecate_args
 
 __all__ = ['Bands']
 
@@ -27,7 +27,7 @@ class Bands:
         calculated.
     args : tuple, defaults to empty
         Positional arguments to pass to the ``hamiltonian`` method.
-        Mutually exclusive with 'params'.
+        Deprecated in favor or 'params' (and mutually exclusive with it).
     params : dict, optional
         Dictionary of parameter names and their values. Mutually exclusive
         with 'args'.
@@ -50,6 +50,7 @@ class Bands:
     """
     _crossover_size = 8
 
+    @deprecate_args
     def __init__(self, sys, args=(), *, params=None):
         syst = sys
         ensure_isinstance(syst, system.InfiniteSystem)
diff --git a/kwant/plotter.py b/kwant/plotter.py
index 4652271cf1870568294798445cc9a6495e1958c7..35813dd325eb1febc3e9a573a44d5b68fef13de8 100644
--- a/kwant/plotter.py
+++ b/kwant/plotter.py
@@ -27,6 +27,7 @@ from scipy import spatial, interpolate
 from math import cos, sin, pi, sqrt
 
 from . import system, builder, _common
+from ._common import deprecate_args
 
 
 __all__ = ['plot', 'map', 'bands', 'spectrum', 'current', 'density',
@@ -1348,6 +1349,7 @@ def map(sys, value, colorbar=True, cmap=None, vmin=None, vmax=None, a=None,
     return fig
 
 
+@deprecate_args
 def bands(sys, args=(), momenta=65, file=None, show=True, dpi=None,
           fig_size=None, ax=None, *, params=None):
     """Plot band structure of a translationally invariant 1D system.
@@ -1358,7 +1360,7 @@ def bands(sys, args=(), momenta=65, file=None, show=True, dpi=None,
         A system bands of which are to be plotted.
     args : tuple, defaults to empty
         Positional arguments to pass to the ``hamiltonian`` method.
-        Mutally exclusive with 'params'.
+        Deprecated in favor of 'params' (and mutually exclusive with it).
     momenta : int or 1D array-like
         Either a number of sampling points on the interval [-pi, pi], or an
         array of points at which the band structure has to be evaluated.
diff --git a/kwant/solvers/common.py b/kwant/solvers/common.py
index 2c3f87a6154fed52fee0153d267f039083a2ef0d..ecf33f80003c6aee65ea5c90c3c75b0f47bc469b 100644
--- a/kwant/solvers/common.py
+++ b/kwant/solvers/common.py
@@ -14,7 +14,7 @@ import abc
 from  numbers import Integral
 import numpy as np
 import scipy.sparse as sp
-from .._common import ensure_isinstance
+from .._common import ensure_isinstance, deprecate_args
 from .. import system
 from functools import reduce
 
@@ -113,7 +113,7 @@ class SparseSolver(metaclass=abc.ABCMeta):
             Excitation energy at which to solve the scattering problem.
         args : tuple, defaults to empty
             Positional arguments to pass to the ``hamiltonian`` method.
-            Mutually exclusive with 'params'.
+            Deprecated in favor of 'params' (and mutually exclusive with it).
         check_hermiticity : bool
             Check if Hamiltonian matrices are in fact Hermitian.
             Enables deduction of missing transmission coefficients.
@@ -296,6 +296,7 @@ class SparseSolver(metaclass=abc.ABCMeta):
 
         return LinearSys(lhs, rhs, indices, num_orb), lead_info
 
+    @deprecate_args
     def smatrix(self, sys, energy=0, args=(),
                 out_leads=None, in_leads=None, check_hermiticity=True,
                 *, params=None):
@@ -313,7 +314,7 @@ class SparseSolver(metaclass=abc.ABCMeta):
             Excitation energy at which to solve the scattering problem.
         args : tuple, defaults to empty
             Positional arguments to pass to the ``hamiltonian`` method.
-            Mutually exclusive with 'params'.
+            Deprecated in favor of 'params' (and mutually exclusive with it).
         out_leads : sequence of integers or ``None``
             Numbers of leads where current or wave function is extracted.  None
             is interpreted as all leads. Default is ``None`` and means "all
@@ -390,6 +391,7 @@ class SparseSolver(metaclass=abc.ABCMeta):
 
         return SMatrix(data, lead_info, out_leads, in_leads, check_hermiticity)
 
+    @deprecate_args
     def greens_function(self, sys, energy=0, args=(),
                         out_leads=None, in_leads=None, check_hermiticity=True,
                         *, params=None):
@@ -407,7 +409,7 @@ class SparseSolver(metaclass=abc.ABCMeta):
             Excitation energy at which to solve the scattering problem.
         args : tuple, defaults to empty
             Positional arguments to pass to the ``hamiltonian`` method.
-            Mutually exclusive with 'params'.
+            Deprecated in favor of 'params' (and mutually exclusive with it).
         out_leads : sequence of integers or ``None``
             Numbers of leads where current or wave function is extracted.  None
             is interpreted as all leads. Default is ``None`` and means "all
@@ -488,6 +490,7 @@ class SparseSolver(metaclass=abc.ABCMeta):
         return GreensFunction(data, lead_info, out_leads, in_leads,
                               check_hermiticity)
 
+    @deprecate_args
     def ldos(self, sys, energy=0, args=(), check_hermiticity=True,
              *, params=None):
         """
@@ -504,8 +507,8 @@ class SparseSolver(metaclass=abc.ABCMeta):
             Excitation energy at which to solve the scattering problem.
         args : tuple of arguments, or empty tuple
             Positional arguments to pass to the function(s) which
-            evaluate the hamiltonian matrix elements.  Mutually exclusive
-            with 'params'.
+            evaluate the hamiltonian matrix elements.
+            Deprecated in favor of 'params' (and mutually exclusive with it).
         check_hermiticity : ``bool``
             Check if the Hamiltonian matrices are Hermitian.
         params : dict, optional
@@ -553,6 +556,7 @@ class SparseSolver(metaclass=abc.ABCMeta):
 
         return ldos * (0.5 / np.pi)
 
+    @deprecate_args
     def wave_function(self, sys, energy=0, args=(), check_hermiticity=True,
                       *, params=None):
         r"""
@@ -568,8 +572,8 @@ class SparseSolver(metaclass=abc.ABCMeta):
             calculated.
         args : tuple of arguments, or empty tuple
             Positional arguments to pass to the function(s) which
-            evaluate the hamiltonian matrix elements. Mutually exclusive
-            with 'params'.
+            evaluate the hamiltonian matrix elements.
+            Deprecated in favor of 'params' (and mutually exclusive with it).
         check_hermiticity : ``bool``
             Check if the Hamiltonian matrices are Hermitian.
         params : dict, optional
diff --git a/kwant/system.py b/kwant/system.py
index 26eea6fa4bc96b38850b9a2a43e8e5ffc2785282..d270691508189866a0d75809917048303443c883 100644
--- a/kwant/system.py
+++ b/kwant/system.py
@@ -14,6 +14,7 @@ import abc
 import warnings
 from copy import copy
 from . import _system
+from ._common  import deprecate_args
 
 
 class System(metaclass=abc.ABCMeta):
@@ -59,12 +60,20 @@ class System(metaclass=abc.ABCMeta):
         if ``i != j``, return the hopping between site ``i`` and ``j``.
 
         Hamiltonians may depend (optionally) on positional and
-        keyword arguments
+        keyword arguments.
+
+        Providing positional arguments via 'args' is deprecated,
+        instead, provide named parameters as a dictionary via 'params'.
         """
         pass
 
+    @deprecate_args
     def discrete_symmetry(self, args, *, params=None):
-        """Return the discrete symmetry of the system."""
+        """Return the discrete symmetry of the system.
+
+        Providing positional arguments via 'args' is deprecated,
+        instead, provide named parameters as a dictionary via 'params'.
+        """
         # Avoid the circular import.
         from .physics import DiscreteSymmetry
         return DiscreteSymmetry()
@@ -131,6 +140,7 @@ class FiniteSystem(System, metaclass=abc.ABCMeta):
 
     """
 
+    @deprecate_args
     def precalculate(self, energy=0, args=(), leads=None,
                      what='modes', *, params=None):
         """
@@ -147,7 +157,7 @@ class FiniteSystem(System, metaclass=abc.ABCMeta):
             evaluated.
         args : sequence
             Additional parameters required for calculating the Hamiltionians.
-            Mutually exclusive with 'params'.
+            Deprecated in favor of 'params' (and mutually exclusive with it).
         leads : sequence of integers or None
             Numbers of the leads to be precalculated. If ``None``, all are
             precalculated.
@@ -194,12 +204,16 @@ class FiniteSystem(System, metaclass=abc.ABCMeta):
         result.leads = new_leads
         return result
 
+    @deprecate_args
     def validate_symmetries(self, args=(), *, params=None):
         """Check that the Hamiltonian satisfies discrete symmetries.
 
         Applies `~kwant.physics.DiscreteSymmetry.validate` to the
         Hamiltonian, see its documentation for details on the return
         format.
+
+        Providing positional arguments via 'args' is deprecated,
+        instead, provide named parameters as a dictionary via 'params'.
         """
         symmetries = self.discrete_symmetry(args=args, params=params)
         ham = self.hamiltonian_submatrix(args, sparse=True, params=params)
@@ -248,19 +262,30 @@ class InfiniteSystem(System, metaclass=abc.ABCMeta):
     exchanged, as well as of site 3 and 4.
 
     """
+    @deprecate_args
     def cell_hamiltonian(self, args=(), sparse=False, *, params=None):
-        """Hamiltonian of a single cell of the infinite system."""
+        """Hamiltonian of a single cell of the infinite system.
+
+        Providing positional arguments via 'args' is deprecated,
+        instead, provide named parameters as a dictionary via 'params'.
+        """
         cell_sites = range(self.cell_size)
         return self.hamiltonian_submatrix(args, cell_sites, cell_sites,
                                           sparse=sparse, params=params)
 
+    @deprecate_args
     def inter_cell_hopping(self, args=(), sparse=False, *, params=None):
-        """Hopping Hamiltonian between two cells of the infinite system."""
+        """Hopping Hamiltonian between two cells of the infinite system.
+
+        Providing positional arguments via 'args' is deprecated,
+        instead, provide named parameters as a dictionary via 'params'.
+        """
         cell_sites = range(self.cell_size)
         interface_sites = range(self.cell_size, self.graph.num_nodes)
         return self.hamiltonian_submatrix(args, cell_sites, interface_sites,
                                           sparse=sparse, params=params)
 
+    @deprecate_args
     def modes(self, energy=0, args=(), *, params=None):
         """Return mode decomposition of the lead
 
@@ -272,6 +297,9 @@ class InfiniteSystem(System, metaclass=abc.ABCMeta):
         freedom on the first ``cell_sites`` sites of the system
         (recall that infinite systems store first the sites in the unit
         cell, then connected sites in the neighboring unit cell).
+
+        Providing positional arguments via 'args' is deprecated,
+        instead, provide named parameters as a dictionary via 'params'.
         """
         from . import physics   # Putting this here avoids a circular import.
         ham = self.cell_hamiltonian(args, params=params)
@@ -301,12 +329,16 @@ class InfiniteSystem(System, metaclass=abc.ABCMeta):
             symmetries.particle_hole = symmetries.chiral = None
         return physics.modes(ham, hop, discrete_symmetry=symmetries)
 
+    @deprecate_args
     def selfenergy(self, energy=0, args=(), *, params=None):
         """Return self-energy of a lead.
 
         The returned matrix has the shape (s, s), where s is
         ``sum(len(self.hamiltonian(i, i)) for i in range(self.graph.num_nodes -
         self.cell_size))``.
+
+        Providing positional arguments via 'args' is deprecated,
+        instead, provide named parameters as a dictionary via 'params'.
         """
         from . import physics   # Putting this here avoids a circular import.
         ham = self.cell_hamiltonian(args, params=params)
@@ -318,12 +350,16 @@ class InfiniteSystem(System, metaclass=abc.ABCMeta):
         return physics.selfenergy(ham,
                                   self.inter_cell_hopping(args, params=params))
 
+    @deprecate_args
     def validate_symmetries(self, args=(), *, params=None):
         """Check that the Hamiltonian satisfies discrete symmetries.
 
         Returns `~kwant.physics.DiscreteSymmetry.validate` applied
         to the onsite matrix and the hopping. See its documentation for
         details on the return format.
+
+        Providing positional arguments via 'args' is deprecated,
+        instead, provide named parameters as a dictionary via 'params'.
         """
         symmetries = self.discrete_symmetry(args=args, params=params)
         ham = self.cell_hamiltonian(args=args, sparse=True, params=params)
@@ -355,6 +391,7 @@ class PrecalculatedLead:
         # is no parametric dependence anymore
         self.parameters = frozenset()
 
+    @deprecate_args
     def modes(self, energy=0, args=(), *, params=None):
         if self._modes is not None:
             return self._modes
@@ -363,6 +400,7 @@ class PrecalculatedLead:
                              "Consider using precalculate() with "
                              "what='modes' or what='all'")
 
+    @deprecate_args
     def selfenergy(self, energy=0, args=(), *, params=None):
         if self._selfenergy is not None:
             return self._selfenergy