def replace(self, expression, replacements):
        """
        All purpose method to reduce an expression by applying
        successive replacement rules.

        `expression` is either a SymPy expression
        or a key in `scipy_data_fitting.Model.expressions`.

        `replacements` can be any of the following,
        or a list of any combination of the following:

        - A replacement tuple as in `scipy_data_fitting.Model.replacements`.
        - The name of a replacement in `scipy_data_fitting.Model.replacements`.
        - The name of a replacement group in `scipy_data_fitting.Model.replacement_groups`.

        Examples:

            #!python
            >>> model.replace(x + y, (x, z))
            z + y

            >>> model.replace('expression', (x, z))
            >>> model.replace('expression', 'replacement')
            >>> model.replace('expression', ['replacement_1', 'replacement_2'])
            >>> model.replace('expression', ['replacement', 'group'])
        """
        # When expression is a string,
        # get the expressions from self.expressions.
        if isinstance(expression, str):
            expression = self.expressions[expression]

        # Allow for replacements to be empty.
        if not replacements:
            return expression

        # Allow replacements to be a string.
        if isinstance(replacements, str):
            if replacements in self.replacements:
                return self.replace(expression, self.replacements[replacements])
            elif replacements in self.replacement_groups:
                return self.replace(expression, self.replacement_groups[replacements])

        # When replacements is a list of strings or tuples,
        # Use reduce to make all the replacements.
        if all(isinstance(item, str) for item in replacements) \
        or all(isinstance(item, tuple) for item in replacements):
            return functools.reduce(self.replace, replacements, expression)

        # Otherwise make the replacement.
        return expression.replace(*replacements)
All purpose method to reduce an expression by applying
        successive replacement rules.

        `expression` is either a SymPy expression
        or a key in `scipy_data_fitting.Model.expressions`.

        `replacements` can be any of the following,
        or a list of any combination of the following:

        - A replacement tuple as in `scipy_data_fitting.Model.replacements`.
        - The name of a replacement in `scipy_data_fitting.Model.replacements`.
        - The name of a replacement group in `scipy_data_fitting.Model.replacement_groups`.

        Examples:

            #!python
            >>> model.replace(x + y, (x, z))
            z + y

            >>> model.replace('expression', (x, z))
            >>> model.replace('expression', 'replacement')
            >>> model.replace('expression', ['replacement_1', 'replacement_2'])
            >>> model.replace('expression', ['replacement', 'group'])