Repository: PennyLaneAI/pennylane
Pull request #4722 (2023-10-24 20:24:47)

Documentation fixes for v0.33
This PR will host all changes to docs for the v0.33 release.

If you open any PRs that *only* update docs, set this branch as the base, and merge once the documentation check and the RTD build pass. Since it is a doc-only change, you can merge without finishing CI.

Try and remember to cancel the tests in CI to save some runners :)

github-actions[bot]: Hello. You may have forgotten to update the changelog!
Please edit [`doc/releases/changelog-dev.md`](/PennyLaneAI/pennylane/blob/master/doc/releases/changelog-dev.md) with:
* A one-to-two sentence description of the change. You may include a small working example for new features.
* A link back to this PR.
* Your name (or GitHub username) in the contributors section.
mudit2812: Closing for now. Will reopen once all fixes are pushed to this branch.

Patch:
diff --git a/doc/development/deprecations.rst b/doc/development/deprecations.rst
index c47244db9..959708a2f 100644
--- a/doc/development/deprecations.rst
+++ b/doc/development/deprecations.rst
@@ -6,6 +6,41 @@ Deprecations
 Pending deprecations
 --------------------
 
+* Passing additional arguments to a transform that decorates a QNode should now be done through use
+  of ``functools.partial``. For example, the :func:`~pennylane.metric_tensor` transform has an
+  optional ``approx`` argument which should now be set using:
+
+  .. code-block:: python
+
+    from functools import partial
+
+    @partial(qml.metric_tensor, approx="block-diag")
+    @qml.qnode(dev)
+    def circuit(weights):
+        ...
+
+  The previously-recommended approach is now deprecated:
+
+  .. code-block:: python
+
+    @qml.metric_tensor(approx="block-diag")
+    @qml.qnode(dev)
+    def circuit(weights):
+        ...
+
+  Alternatively, consider calling the transform directly:
+
+  .. code-block:: python
+
+    @qml.qnode(dev)
+    def circuit(weights):
+        ...
+
+    transformed_circuit = qml.metric_tensor(circuit, approx="block-diag")
+
+  - Deprecated in v0.33
+  - Will be removed in v0.35
+
 * ``qml.ExpvalCost`` has been deprecated, and usage will now raise a warning.
   
   - Deprecated in v0.24
@@ -155,29 +190,6 @@ Completed deprecation cycles
   - Deprecated in v0.32
   - Removed in v0.33
 
-* The following decorator syntax for transforms has been deprecated:
-
-  .. code-block:: python
-
-      @transform_fn(**transform_kwargs)
-      @qml.qnode(dev)
-      def circuit():
-          ...
-
-  If you are using a transform that has supporting ``transform_kwargs``, please call the
-  transform directly using ``circuit = transform_fn(circuit, **transform_kwargs)``,
-  or use ``functools.partial``:
-
-  .. code-block:: python
-
-      @functools.partial(transform_fn, **transform_kwargs)
-      @qml.qnode(dev)
-      def circuit():
-          ...
-
-  - Deprecated in v0.33
-  - Will be removed in v0.34
-
 * The ``mode`` keyword argument in ``QNode`` has been removed, as it was only used in the old return
   system (which has also been removed). Please use ``grad_on_execution`` instead.
 
diff --git a/doc/introduction/compiling_circuits.rst b/doc/introduction/compiling_circuits.rst
index 843717907..ef8298547 100644
--- a/doc/introduction/compiling_circuits.rst
+++ b/doc/introduction/compiling_circuits.rst
@@ -135,9 +135,9 @@ For example, take the following decorated quantum function:
 
     dev = qml.device('default.qubit', wires=[0, 1, 2])
 
+    @qml.compile
     @qml.qnode(dev)
-    @qml.compile()
-    def qfunc(x, y, z):
+    def circuit(x, y, z):
         qml.Hadamard(wires=0)
         qml.Hadamard(wires=1)
         qml.Hadamard(wires=2)
@@ -157,7 +157,7 @@ The default behaviour of :func:`~.pennylane.compile` applies a sequence of three
 transforms: :func:`~.pennylane.transforms.commute_controlled`, :func:`~.pennylane.transforms.cancel_inverses`,
 and then :func:`~.pennylane.transforms.merge_rotations`.
 
->>> print(qml.draw(qfunc)(0.2, 0.3, 0.4))
+>>> print(qml.draw(circuit)(0.2, 0.3, 0.4))
 0: ──H──RX(0.60)─────────────────┤  <Z>
 1: ──H─╭X─────────────────────╭●─┤     
 2: ──H─╰●─────────RX(0.30)──Y─╰Z─┤     
@@ -173,8 +173,8 @@ controlled gates and cancel adjacent inverses, we could do:
     from pennylane.transforms import commute_controlled, cancel_inverses
     pipeline = [commute_controlled, cancel_inverses]
 
+    @partial(qml.compile, pipeline=pipeline)
     @qml.qnode(dev)
-    @qml.compile(pipeline=pipeline)
     def qfunc(x, y, z):
         qml.Hadamard(wires=0)
         qml.Hadamard(wires=1)
diff --git a/pennylane/__init__.py b/pennylane/__init__.py
index 0d869bf99..09b2c34c6 100644
--- a/pennylane/__init__.py
+++ b/pennylane/__init__.py
@@ -82,6 +82,7 @@ from pennylane.templates.subroutines import *
 from pennylane import qaoa
 from pennylane.qnode import QNode, qnode
 from pennylane.transforms import (
+    transform,
     adjoint_metric_tensor,
     batch_params,
     batch_input,
@@ -165,8 +166,8 @@ plugin_devices = _get_device_entrypoints()
 
 # pylint: disable=protected-access
 def device(name, *args, **kwargs):
-    r"""device(name, wires=1, *args, **kwargs)
-    Load a :class:`~.Device` and return the instance.
+    r"""
+    Load a device and return the instance.
 
     This function is used to load a particular quantum device,
     which can then be used to construct QNodes.
@@ -176,36 +177,39 @@ def device(name, *args, **kwargs):
     * :mod:`'default.qubit' <pennylane.devices.default_qubit>`: a simple
       state simulator of qubit-based quantum circuit architectures.
 
-    * :mod:`'default.gaussian' <pennylane.devices.default_gaussian>`: a simple simulator
-      of Gaussian states and operations on continuous-variable circuit architectures.
+    * :mod:`'default.mixed' <pennylane.devices.default_mixed>`: a mixed-state
+      simulator of qubit-based quantum circuit architectures.
 
-    * :mod:`'default.qubit.tf' <pennylane.devices.default_qubit_tf>`: a state simulator
-      of qubit-based quantum circuit architectures written in TensorFlow, which allows
-      automatic differentiation through the simulation.
+    * ``'lightning.qubit'``: a more performant state simulator of qubit-based
+      quantum circuit architectures written in C++.
 
-    * :mod:`'default.qubit.autograd' <pennylane.devices.default_qubit_autograd>`: a state simulator
-      of qubit-based quantum circuit architectures which allows
-      automatic differentiation through the simulation via python's autograd library.
+    * :mod:`'default.qutrit' <pennylane.devices.default_qutrit>`: a simple
+      state simulator of qutrit-based quantum circuit architectures.
+
+    * :mod:`'default.gaussian' <pennylane.devices.default_gaussian>`: a simple simulator
+      of Gaussian states and operations on continuous-variable circuit architectures.
 
     Additional devices are supported through plugins — see
     the  `available plugins <https://pennylane.ai/plugins.html>`_ for more
-    details.
+    details. To list all currently installed devices, run
+    :func:`qml.about <pennylane.about>`.
 
     Args:
         name (str): the name of the device to load
         wires (int): the number of wires (subsystems) to initialise
-            the device with
+            the device with. Note that this is optional for certain
+            devices, such as ``default.qubit``
 
     Keyword Args:
         config (pennylane.Configuration): a PennyLane configuration object
             that contains global and/or device specific configurations.
-        custom_decomps (Dict[Union(str, qml.Operator), Callable]): Custom
+        custom_decomps (Dict[Union(str, Operator), Callable]): Custom
             decompositions to be applied by the device at runtime.
         decomp_depth (int): For when custom decompositions are specified,
             the maximum expansion depth used by the expansion function.
 
     All devices must be loaded by specifying their **short-name** as listed above,
-    followed by the **wires** (subsystems) you wish to initialize. The *wires*
+    followed by the **wires** (subsystems) you wish to initialize. The ``wires``
     argument can be an integer, in which case the wires of the device are addressed
     by consecutive integers:
 
@@ -219,7 +223,7 @@ def device(name, *args, **kwargs):
            qml.CNOT(wires=[3, 4])
            ...
 
-    The *wires* argument can also be a sequence of unique numbers or strings, specifying custom wire labels
+    The ``wires`` argument can also be a sequence of unique numbers or strings, specifying custom wire labels
     that the user employs to address the wires:
 
     .. code-block:: python
@@ -232,10 +236,16 @@ def device(name, *args, **kwargs):
            qml.CNOT(wires=['q12', -1])
            ...
 
+    On some newer devices, such as ``default.qubit``, the ``wires`` argument can be omitted altogether,
+    and instead the wires will be computed when executing a circuit depending on its contents.
+
+    >>> dev = qml.device("default.qubit")
+
     Most devices accept a ``shots`` argument which specifies how many circuit executions
-    are used to estimate stochastic return values. In particular, ``qml.sample()`` measurements
+    are used to estimate stochastic return values. As an example, ``qml.sample()`` measurements
     will return as many samples as specified in the shots argument. The shots argument can be
-    changed on a per-call basis using the built-in ``shots`` keyword argument.
+    changed on a per-call basis using the built-in ``shots`` keyword argument. Note that the
+    ``shots`` argument can be a single integer or a list of shot values.
 
     .. code-block:: python
 
@@ -247,11 +257,11 @@ def device(name, *args, **kwargs):
           return qml.sample(qml.PauliZ(wires=0))
 
     >>> circuit(0.8)  # 10 samples are returned
-    [ 1  1  1 -1 -1  1  1  1  1  1]
-    >>> circuit(0.8, shots=3)   # default is overwritten for this call
-    [1 1 1]
+    array([ 1,  1,  1,  1, -1,  1,  1, -1,  1,  1])
+    >>> circuit(0.8, shots=[3, 4, 4])   # default is overwritten for this call
+    (array([1, 1, 1]), array([ 1, -1,  1,  1]), array([1, 1, 1, 1]))
     >>> circuit(0.8)  # back to default of 10 samples
-    [ 1  1  1 -1 -1  1  1  1  1  1]
+    array([ 1, -1,  1,  1, -1,  1,  1,  1,  1,  1])
 
     When constructing a device, we may optionally pass a dictionary of custom
     decompositions to be applied to certain operations upon device execution.
diff --git a/pennylane/devices/device_api.py b/pennylane/devices/device_api.py
index 749f0a186..1d8c5c352 100644
--- a/pennylane/devices/device_api.py
+++ b/pennylane/devices/device_api.py
@@ -236,7 +236,7 @@ class Device(abc.ABC):
         **Example**
 
         All the transforms that are part of the preprocessing need to respect the transform contract defined in
-        :func:`pennylane.transforms.core.transform`.
+        :func:`pennylane.transform`.
 
         .. code-block:: python
 
diff --git a/pennylane/devices/preprocess.py b/pennylane/devices/preprocess.py
index 7444e96bf..8b988048d 100644
--- a/pennylane/devices/preprocess.py
+++ b/pennylane/devices/preprocess.py
@@ -30,7 +30,7 @@ from pennylane.measurements import (
 )
 from pennylane.typing import ResultBatch, Result
 from pennylane import DeviceError
-from pennylane.transforms.core import transform
+from pennylane import transform
 from pennylane.wires import WireError
 
 PostprocessingFn = Callable[[ResultBatch], Union[Result, ResultBatch]]
@@ -87,8 +87,14 @@ def no_sampling(
     """Raises an error if the tape has finite shots.
 
     Args:
-        tape (QuantumTape): a quantum circuit
-        name="device" (str): name to use in error message.
+        tape (QuantumTape or .QNode or Callable): a quantum circuit
+        name (str): name to use in error message.
+
+    Returns:
+        qnode (QNode) or quantum function (Callable) or tuple[List[.QuantumTape], function]:
+
+        The unaltered input circuit. The output type is explained in :func:`qml.transform <pennylane.transform>`.
+
 
     This transform can be added to forbid finite shots. For example, ``default.qubit`` uses it for
     adjoint and backprop validation.
@@ -107,17 +113,15 @@ def validate_device_wires(
     across all available wires.
 
     Args:
-        tape (QuantumTape): a quantum circuit.
+        tape (QuantumTape or QNode or Callable): a quantum circuit.
         wires=None (Optional[Wires]): the allowed wires. Wires of ``None`` allows any wires
             to be present in the tape.
         name="device" (str): the name of the device to use in error messages.
 
     Returns:
-        pennylane.QNode or qfunc or Tuple[List[.QuantumTape], Callable]: If a QNode is passed,
-        it returns a QNode with the transform added to its transform program.
-        If a tape is passed, returns a tuple containing a list of
-        quantum tapes to be evaluated, and a function to be applied to these
-        tape executions.
+        qnode (QNode) or quantum function (Callable) or tuple[List[QuantumTape], function]:
+
+        The unaltered input circuit. The output type is explained in :func:`qml.transform <pennylane.transform>`.
 
     Raises:
         WireError: if the tape has a wire not present in the provided wires.
@@ -153,16 +157,15 @@ def validate_multiprocessing_workers(
     threads per worker.
 
     Args:
-        tape (QuantumTape): a quantum circuit.
+        tape (QuantumTape or .QNode or Callable): a quantum circuit.
         max_workers (int): Maximal number of multiprocessing workers
         device (pennylane.devices.Device): The device to be checked.
 
     Returns:
-        pennylane.QNode or qfunc or Tuple[List[.QuantumTape], Callable]: If a QNode is passed,
-        it returns a QNode with the transform added to its transform program.
-        If a tape is passed, returns a tuple containing a list of
-        quantum tapes to be evaluated, and a function to be applied to these
-        tape executions.
+        qnode (pennylane.QNode) or quantum function (callable) or tuple[List[.QuantumTape], function]:
+
+        The unaltered input circuit. The output type is explained in :func:`qml.transform <pennylane.transform>`.
+
     """
     if max_workers is not None:
         threads_per_proc = os.cpu_count()  # all threads by default
@@ -238,7 +241,7 @@ def decompose(
     """Decompose operations until the stopping condition is met.
 
     Args:
-        tape (QuantumTape): a quantum circuit.
+        tape (QuantumTape or QNode or Callable): a quantum circuit.
         stopping_condition (Callable): a function from an operator to a boolean. If ``False``, the operator
             should be decomposed. If an operator cannot be decomposed and is not accepted by ``stopping_condition``,
             a ``DecompositionUndefinedError`` will be raised.
@@ -249,11 +252,9 @@ def decompose(
 
 
     Returns:
-        pennylane.QNode or qfunc or Tuple[List[.QuantumTape], Callable]: If a QNode is passed,
-        it returns a QNode with the transform added to its transform program.
-        If a tape is passed, returns a tuple containing a list of
-        quantum tapes to be evaluated, and a function to be applied to these
-        tape executions.
+        qnode (QNode) or quantum function (Callable) or tuple[List[QuantumTape], function]:
+
+        The decomposed circuit. The output type is explained in :func:`qml.transform <pennylane.transform>`.
 
     Raises:
         DecompositionUndefinedError: if an operator is not accepted and does not define a decomposition
@@ -339,16 +340,14 @@ def validate_observables(
     """Validates the observables and measurements for a circuit.
 
     Args:
-        tape (QuantumTape): a quantum circuit.
+        tape (QuantumTape or QNode or Callable): a quantum circuit.
         stopping_condition (callable): a function that specifies whether or not an observable is accepted.
         name (str): the name of the device to use in error messages.
 
     Returns:
-        pennylane.QNode or qfunc or Tuple[List[.QuantumTape], Callable]: If a QNode is passed,
-        it returns a QNode with the transform added to its transform program.
-        If a tape is passed, returns a tuple containing a list of
-        quantum tapes to be evaluated, and a function to be applied to these
-        tape executions.
+        qnode (QNode) or quantum function (Callable) or tuple[List[.QuantumTape], function]:
+
+        The unaltered input circuit. The output type is explained in :func:`qml.transform <pennylane.transform>`.
 
     Raises:
         DeviceError: if an observable is not supported
@@ -383,7 +382,7 @@ def validate_measurements(
     """Validates the supported state and sample based measurement processes.
 
     Args:
-        tape (QuantumTape): a quantum circuit.
+        tape (QuantumTape, .QNode, Callable): a quantum circuit.
         analytic_measurements (Callable[[MeasurementProcess], bool]): a function from a measurement process
             to whether or not it is accepted in analytic simulations.
         sample_measurements (Callable[[MeasurementProcess], bool]): a function from a measurement process
@@ -391,11 +390,9 @@ def validate_measurements(
         name (str): the name to use in error messages.
 
     Returns:
-        pennylane.QNode or qfunc or Tuple[List[.QuantumTape], Callable]: If a QNode is passed,
-        it returns a QNode with the transform added to its transform program.
-        If a tape is passed, returns a tuple containing a list of
-        quantum tapes to be evaluated, and a function to be applied to these
-        tape executions.
+        qnode (pennylane.QNode) or quantum function (callable) or tuple[List[.QuantumTape], function]:
+
+        The unaltered input circuit. The output type is explained in :func:`qml.transform <pennylane.transform>`.
 
     Raises:
         DeviceError: if a measurement process is not supported.
diff --git a/pennylane/fourier/circuit_spectrum.py b/pennylane/fourier/circuit_spectrum.py
index fd861f1c6..5c95f32b5 100644
--- a/pennylane/fourier/circuit_spectrum.py
+++ b/pennylane/fourier/circuit_spectrum.py
@@ -16,7 +16,7 @@ of a quantum circuit, that is the frequencies without considering
 preprocessing in the QNode."""
 from typing import Sequence, Callable
 from functools import partial
-from pennylane.transforms.core import transform
+from pennylane import transform
 from pennylane.tape import QuantumTape
 from .utils import get_spectrum, join_spectra
 
@@ -48,15 +48,17 @@ def circuit_spectrum(
         If no input-encoding gates are found, an empty dictionary is returned.
 
     Args:
-        tape (QuantumTape): a quantum node representing a circuit in which
+        tape (QNode or QuantumTape or Callable): a quantum circuit in which
             input-encoding gates are marked by their ``id`` attribute
         encoding_gates (list[str]): list of input-encoding gate ``id`` strings
             for which to compute the frequency spectra
         decimals (int): number of decimals to which to round frequencies.
 
     Returns:
-        (dict[str, list[float]]): Dictionary with the input-encoding gate ``id`` as keys and
-        their frequency spectra as values.
+        qnode (QNode) or quantum function (Callable) or tuple[List[QuantumTape], function]:
+
+        The transformed circuit as described in :func:`qml.transform <pennylane.transform>`. Executing this circuit
+        will return a dictionary with the input-encoding gate ``id`` as keys and their frequency spectra as values.
 
 
     **Details**
@@ -185,6 +187,7 @@ def circuit_spectrum(
     """
 
     def processing_fn(tapes):
+        """Process the tapes extract the spectrum of the circuit."""
         tape = tapes[0]
         freqs = {}
         for op in tape.operations:
diff --git a/pennylane/gradients/__init__.py b/pennylane/gradients/__init__.py
index 1bbd0dbf4..13c9fe6f6 100644
--- a/pennylane/gradients/__init__.py
+++ b/pennylane/gradients/__init__.py
@@ -51,15 +51,6 @@ Gradient transforms
     stoch_pulse_grad
     pulse_odegen
 
-Custom gradients
-^^^^^^^^^^^^^^^^
-
-.. autosummary::
-    :toctree: api
-
-    gradient_transform
-    hessian_transform
-
 Utility functions
 ^^^^^^^^^^^^^^^^^
 
@@ -131,7 +122,10 @@ for each QNode will be used.
 Transforming QNodes
 -------------------
 
-Alternatively, quantum gradient transforms can be applied manually to QNodes.
+Alternatively, quantum gradient transforms can be applied manually to QNodes. This is not
+recommended because PennyLane must compute the classical Jacobian of the parameters and multiply it with
+the quantum Jacobian, we recommend using the ``diff_method`` kwargs with your favorite machine learning
+framework.
 
 .. code-block:: python
 
@@ -304,13 +298,13 @@ from executing the gradient tapes.
 Custom gradient transforms
 --------------------------
 
-Using the :class:`~.gradient_transform` decorator, custom gradient transforms
+Using the :func:`qml.transform <pennylane.transform>` decorator, custom gradient transforms
 can be created:
 
 .. code-block:: python
 
-    @gradient_transform
-    def my_custom_gradient(tape, **kwargs):
+    @transform
+    def my_custom_gradient(tape: qml.tape.QuantumTape, **kwargs) -> (Sequence[qml.tape.QuantumTape], Callable):
         ...
         return gradient_tapes, processing_fn
 
@@ -318,7 +312,7 @@ Once created, a custom gradient transform can be applied directly
 to QNodes, or registered as the quantum gradient transform to use
 during autodifferentiation.
 
-For more details, please see the :class:`~.gradient_transform`
+For more details, please see the :func:`qml.transform <pennylane.transform>`
 documentation.
 """
 import pennylane as qml
diff --git a/pennylane/gradients/finite_difference.py b/pennylane/gradients/finite_difference.py
index 643f21333..767a2ce66 100644
--- a/pennylane/gradients/finite_difference.py
+++ b/pennylane/gradients/finite_difference.py
@@ -26,7 +26,7 @@ from scipy.special import factorial
 
 import pennylane as qml
 from pennylane.measurements import ProbabilityMP
-from pennylane.transforms.core import transform
+from pennylane import transform
 from pennylane.transforms.tape_expand import expand_invalid_trainable
 from pennylane.gradients.gradient_transform import _contract_qjac_with_cjac
 
@@ -210,10 +210,10 @@ def finite_diff(
     f0=None,
     validate_params=True,
 ) -> (Sequence[qml.tape.QuantumTape], Callable):
-    r"""Transform a QNode to compute the finite-difference gradient of all gate parameters with respect to its inputs.
+    r"""Transform a circuit to compute the finite-difference gradient of all gate parameters with respect to its inputs.
 
     Args:
-        tape (pennylane.QNode or .QuantumTape): quantum tape or QNode to differentiate
+        tape (QNode or QuantumTape): quantum circuit to differentiate
         argnum (int or list[int] or None): Trainable parameter indices to differentiate
             with respect to. If not provided, the derivatives with respect to all
             trainable parameters are returned.
@@ -237,17 +237,11 @@ def finite_diff(
             If ``False``, the finite-difference method will be applied to all parameters.
 
     Returns:
-        function or tuple[list[QuantumTape], function]:
+        qnode (QNode) or tuple[List[QuantumTape], function]:
 
-        - If the input is a QNode, an object representing the Jacobian (function) of the QNode
-          that can be executed to obtain the Jacobian.
-          The type of the Jacobian returned is either a tensor, a tuple or a
-          nested tuple depending on the nesting structure of the original QNode output.
-
-        - If the input is a tape, a tuple containing a
-          list of generated tapes, together with a post-processing
-          function to be applied to the results of the evaluated tapes
-          in order to obtain the Jacobian.
+        The transformed circuit as described in :func:`qml.transform <pennylane.transform>`. Executing this circuit
+        will provide the Jacobian in the form of a tensor, a tuple, or a nested tuple depending upon the nesting
+        structure of measurements in the original circuit.
 
     **Example**
 
@@ -287,7 +281,9 @@ def finite_diff(
     .. details::
         :title: Usage Details
 
-        This gradient transform can also be applied directly to :class:`QNode <pennylane.QNode>` objects:
+        This gradient transform can be applied directly to :class:`QNode <pennylane.QNode>` objects.
+        However, for performance reasons, we recommend providing the gradient transform as the ``diff_method`` argument
+        of the QNode decorator, and differentiating with your preferred machine learning framework.
 
         >>> @qml.qnode(dev)
         ... def circuit(params):
diff --git a/pennylane/gradients/hadamard_gradient.py b/pennylane/gradients/hadamard_gradient.py
index 05f9081e2..91bd0ab09 100644
--- a/pennylane/gradients/hadamard_gradient.py
+++ b/pennylane/gradients/hadamard_gradient.py
@@ -21,7 +21,7 @@ from functools import partial
 import pennylane as qml
 import pennylane.numpy as np
 from pennylane.transforms.metric_tensor import _get_aux_wire
-from pennylane.transforms.core import transform
+from pennylane import transform
 from pennylane.gradients.gradient_transform import _contract_qjac_with_cjac
 from pennylane.transforms.tape_expand import expand_invalid_trainable_hadamard_gradient
 
@@ -66,10 +66,10 @@ def hadamard_grad(
     aux_wire=None,
     device_wires=None,
 ) -> (Sequence[qml.tape.QuantumTape], Callable):
-    r"""Transform a QNode to compute the Hadamard test gradient of all gates with respect to their inputs.
+    r"""Transform a circuit to compute the Hadamard test gradient of all gates with respect to their inputs.
 
     Args:
-        tape (pennylane.QNode or .QuantumTape): quantum tape or QNode to differentiate
+        tape (QNode or QuantumTape): quantum circuit to differentiate
         argnum (int or list[int] or None): Trainable tape parameter indices to differentiate
             with respect to. If not provided, the derivatives with respect to all
             trainable parameters are returned.
@@ -80,17 +80,11 @@ def hadamard_grad(
             is ``None``.
 
     Returns:
-        function or tuple[list[QuantumTape], function]:
+        qnode (QNode) or tuple[List[QuantumTape], function]:
 
-        - If the input is a QNode, an object representing the Jacobian (function) of the QNode
-          that can be executed to obtain the Jacobian.
-          The type of the Jacobian returned is either a tensor, a tuple or a
-          nested tuple depending on the nesting structure of the original QNode output.
-
-        - If the input is a tape, a tuple containing a
-          list of generated tapes, together with a post-processing
-          function to be applied to the results of the evaluated tapes
-          in order to obtain the Jacobian.
+        The transformed circuit as described in :func:`qml.transform <pennylane.transform>`. Executing this circuit
+        will provide the Jacobian in the form of a tensor, a tuple, or a nested tuple depending upon the nesting
+        structure of measurements in the original circuit.
 
     For a variational evolution :math:`U(\mathbf{p}) \vert 0\rangle` with
     :math:`N` parameters :math:`\mathbf{p}`,
@@ -114,74 +108,93 @@ def hadamard_grad(
 
     **Example**
 
-    This gradient transform can be applied directly to :class:`QNode <pennylane.QNode>` objects:
-
-    >>> dev = qml.device("default.qubit", wires=2)
-    >>> @qml.qnode(dev)
-    ... def circuit(params):
-    ...     qml.RX(params[0], wires=0)
-    ...     qml.RY(params[1], wires=0)
-    ...     qml.RX(params[2], wires=0)
-    ...     return qml.expval(qml.PauliZ(0))
-    >>> params = np.array([0.1, 0.2, 0.3], requires_grad=True)
-    >>> qml.gradients.hadamard_grad(circuit)(params)
-    (tensor(-0.3875172, requires_grad=True),
-     tensor(-0.18884787, requires_grad=True),
-     tensor(-0.38355704, requires_grad=True))
-
-    This quantum gradient transform can also be applied to low-level
-    :class:`~.QuantumTape` objects. This will result in no implicit quantum
-    device evaluation. Instead, the processed tapes, and post-processing
-    function, which together define the gradient are directly returned:
-
-    >>> ops = [qml.RX(params[0], 0), qml.RY(params[1], 0), qml.RX(params[2], 0)]
-    >>> measurements = [qml.expval(qml.PauliZ(0))]
-    >>> tape = qml.tape.QuantumTape(ops, measurements)
-    >>> gradient_tapes, fn = qml.gradients.hadamard_grad(tape)
-    >>> gradient_tapes
-    [<QuantumTape: wires=[0, 1], params=3>,
-     <QuantumTape: wires=[0, 1], params=3>,
-     <QuantumTape: wires=[0, 1], params=3>]
-
-    This can be useful if the underlying circuits representing the gradient
-    computation need to be analyzed.
-
-    The output tapes can then be evaluated and post-processed to retrieve
-    the gradient:
-
-    >>> dev = qml.device("default.qubit", wires=2)
-    >>> fn(qml.execute(gradient_tapes, dev, None))
-    (tensor(-0.3875172, requires_grad=True),
-     tensor(-0.18884787, requires_grad=True),
-     tensor(-0.38355704, requires_grad=True))
-
     This transform can be registered directly as the quantum gradient transform
     to use during autodifferentiation:
 
-    >>> dev = qml.device("default.qubit", wires=3)
+    >>> import jax
+    >>> dev = qml.device("default.qubit", wires=2)
     >>> @qml.qnode(dev, interface="jax", diff_method="hadamard")
     ... def circuit(params):
     ...     qml.RX(params[0], wires=0)
     ...     qml.RY(params[1], wires=0)
     ...     qml.RX(params[2], wires=0)
-    ...     return qml.expval(qml.PauliZ(0))
-    >>> params = jax.numpy.array([0.1, 0.2, 0.3])
-    >>> jax.jacobian(circuit)(params)
-    Array([-0.3875172 , -0.18884787, -0.38355704], dtype=float64)
-
-    If you use custom wires on your device, you need to pass an auxiliary wire.
-
-    >>> dev_wires = ("a", "c")
-    >>> dev = qml.device("default.qubit", wires=dev_wires)
-    >>> @qml.qnode(dev, interface="jax", diff_method="hadamard", aux_wire="c", device_wires=dev_wires)
-    >>> def circuit(params):
-    ...    qml.RX(params[0], wires="a")
-    ...    qml.RY(params[1], wires="a")
-    ...    qml.RX(params[2], wires="a")
-    ...    return qml.expval(qml.PauliZ("a"))
+    ...     return qml.expval(qml.PauliZ(0)), qml.var(qml.PauliZ(0))
     >>> params = jax.numpy.array([0.1, 0.2, 0.3])
     >>> jax.jacobian(circuit)(params)
-    Array([-0.3875172 , -0.18884787, -0.38355704], dtype=float64)
+    (Array([-0.38751727, -0.18884793, -0.3835571 ], dtype=float32),
+    Array([0.6991687 , 0.34072432, 0.6920237 ], dtype=float32))
+
+    .. details::
+        :title: Usage Details
+
+        This gradient transform can be applied directly to :class:`QNode <pennylane.QNode>` objects.
+        However, for performance reasons, we recommend providing the gradient transform as the ``diff_method`` argument
+        of the QNode decorator, and differentiating with your preferred machine learning framework.
+
+        >>> dev = qml.device("default.qubit", wires=2)
+        >>> @qml.qnode(dev)
+        ... def circuit(params):
+        ...     qml.RX(params[0], wires=0)
+        ...     qml.RY(params[1], wires=0)
+        ...     qml.RX(params[2], wires=0)
+        ...     return qml.expval(qml.PauliZ(0))
+        >>> params = np.array([0.1, 0.2, 0.3], requires_grad=True)
+        >>> qml.gradients.hadamard_grad(circuit)(params)
+        (tensor([-0.3875172], requires_grad=True),
+         tensor([-0.18884787], requires_grad=True),
+         tensor([-0.38355704], requires_grad=True))
+
+        This quantum gradient transform can also be applied to low-level
+        :class:`~.QuantumTape` objects. This will result in no implicit quantum
+        device evaluation. Instead, the processed tapes, and post-processing
+        function, which together define the gradient are directly returned:
+
+        >>> ops = [qml.RX(p, wires=0) for p in params]
+        >>> measurements = [qml.expval(qml.PauliZ(0))]
+        >>> tape = qml.tape.QuantumTape(ops, measurements)
+        >>> gradient_tapes, fn = qml.gradients.hadamard_grad(tape)
+        >>> gradient_tapes
+        [<QuantumTape: wires=[0, 1], params=3>,
+         <QuantumTape: wires=[0, 1], params=3>,
+         <QuantumTape: wires=[0, 1], params=3>]
+
+        This can be useful if the underlying circuits representing the gradient
+        computation need to be analyzed.
+
+        The output tapes can then be evaluated and post-processed to retrieve
+        the gradient:
+
+        >>> dev = qml.device("default.qubit", wires=2)
+        >>> fn(qml.execute(gradient_tapes, dev, None))
+        (array(-0.3875172), array(-0.18884787), array(-0.38355704))
+
+        This transform can be registered directly as the quantum gradient transform
+        to use during autodifferentiation:
+
+        >>> dev = qml.device("default.qubit", wires=3)
+        >>> @qml.qnode(dev, interface="jax", diff_method="hadamard")
+        ... def circuit(params):
+        ...     qml.RX(params[0], wires=0)
+        ...     qml.RY(params[1], wires=0)
+        ...     qml.RX(params[2], wires=0)
+        ...     return qml.expval(qml.PauliZ(0))
+        >>> params = jax.numpy.array([0.1, 0.2, 0.3])
+        >>> jax.jacobian(circuit)(params)
+        [-0.3875172  -0.18884787 -0.38355704]
+
+        If you use custom wires on your device, you need to pass an auxiliary wire.
+
+        >>> dev_wires = ("a", "c")
+        >>> dev = qml.device("default.qubit", wires=dev_wires)
+        >>> @qml.qnode(dev, interface="jax", diff_method="hadamard", aux_wire="c", device_wires=dev_wires)
+        >>> def circuit(params):
+        ...    qml.RX(params[0], wires="a")
+        ...    qml.RY(params[1], wires="a")
+        ...    qml.RX(params[2], wires="a")
+        ...    return qml.expval(qml.PauliZ("a"))
+        >>> params = jax.numpy.array([0.1, 0.2, 0.3])
+        >>> jax.jacobian(circuit)(params)
+        [-0.3875172  -0.18884787 -0.38355704]
 
     .. note::
 
diff --git a/pennylane/gradients/parameter_shift.py b/pennylane/gradients/parameter_shift.py
index de540e4d6..f058d700f 100644
--- a/pennylane/gradients/parameter_shift.py
+++ b/pennylane/gradients/parameter_shift.py
@@ -23,7 +23,7 @@ import numpy as np
 
 import pennylane as qml
 from pennylane.measurements import VarianceMP
-from pennylane.transforms.core import transform
+from pennylane import transform
 from pennylane.transforms.tape_expand import expand_invalid_trainable
 from pennylane.gradients.gradient_transform import _contract_qjac_with_cjac
 
@@ -759,11 +759,11 @@ def param_shift(
     f0=None,
     broadcast=False,
 ) -> (Sequence[qml.tape.QuantumTape], Callable):
-    r"""Transform a QNode to compute the parameter-shift gradient of all gate
+    r"""Transform a circuit to compute the parameter-shift gradient of all gate
     parameters with respect to its inputs.
 
     Args:
-        qnode (pennylane.QNode or .QuantumTape): quantum tape or QNode to differentiate
+        tape (QNode or QuantumTape): quantum circuit to differentiate
         argnum (int or list[int] or None): Trainable parameter indices to differentiate
             with respect to. If not provided, the derivative with respect to all
             trainable indices are returned.
@@ -794,17 +794,11 @@ def param_shift(
             a single broadcasted tape per operation instead of one tape per shift angle.
 
     Returns:
-        function or tuple[list[QuantumTape], function]:
+        qnode (QNode) or tuple[List[QuantumTape], function]:
 
-        - If the input is a QNode, an object representing the Jacobian (function) of the QNode
-          that can be executed to obtain the Jacobian.
-          The type of the Jacobian returned is either a tensor, a tuple or a
-          nested tuple depending on the nesting structure of the original QNode output.
-
-        - If the input is a tape, a tuple containing a
-          list of generated tapes, together with a post-processing
-          function to be applied to the results of the evaluated tapes
-          in order to obtain the Jacobian.
+        The transformed circuit as described in :func:`qml.transform <pennylane.transform>`. Executing this circuit
+        will provide the Jacobian in the form of a tensor, a tuple, or a nested tuple depending upon the nesting
+        structure of measurements in the original circuit.
 
     For a variational evolution :math:`U(\mathbf{p}) \vert 0\rangle` with
     :math:`N` parameters :math:`\mathbf{p}`,
@@ -928,7 +922,9 @@ def param_shift(
     .. details::
         :title: Usage Details
 
-        This gradient transform can be applied directly to :class:`QNode <pennylane.QNode>` objects:
+        This gradient transform can be applied directly to :class:`QNode <pennylane.QNode>` objects.
+        However, for performance reasons, we recommend providing the gradient transform as the ``diff_method`` argument
+        of the QNode decorator, and differentiating with your preferred machine learning framework.
 
         >>> @qml.qnode(dev)
         ... def circuit(params):
diff --git a/pennylane/gradients/parameter_shift_cv.py b/pennylane/gradients/parameter_shift_cv.py
index 06b328209..369fbf2fc 100644
--- a/pennylane/gradients/parameter_shift_cv.py
+++ b/pennylane/gradients/parameter_shift_cv.py
@@ -25,7 +25,7 @@ import numpy as np
 
 import pennylane as qml
 from pennylane.measurements import ExpectationMP, ProbabilityMP, StateMP, VarianceMP
-from pennylane.transforms.core import transform
+from pennylane import transform
 from pennylane.transforms.tape_expand import expand_invalid_trainable
 from pennylane.gradients.gradient_transform import _contract_qjac_with_cjac
 
@@ -524,7 +524,7 @@ def param_shift_cv(
     parameters with respect to its inputs.
 
     Args:
-        tape (.QuantumTape): quantum tape to differentiate
+        tape (QNode or QuantumTape): quantum circuit to differentiate
         dev (pennylane.Device): device the parameter-shift method is to be computed on
         argnum (int or list[int] or None): Trainable parameter indices to differentiate
             with respect to. If not provided, the derivative with respect to all
@@ -556,16 +556,11 @@ def param_shift_cv(
         force_order2 (bool): if True, use the order-2 method even if not necessary
 
     Returns:
-        function or tuple[list[QuantumTape], function]:
-
-        - If the input is a QNode, an object representing the Jacobian (function) of the QNode
-          that can be executed to obtain the Jacobian matrix.
-          The returned matrix is a tensor of size ``(number_outputs, number_gate_parameters)``
+        qnode (QNode) or tuple[List[QuantumTape], function]:
 
-        - If the input is a tape, a tuple containing a
-          list of generated tapes, together with a post-processing
-          function to be applied to the results of the evaluated tapes
-          in order to obtain the Jacobian matrix.
+        The transformed circuit as described in :func:`qml.transform <pennylane.transform>`. Executing this circuit
+        will provide the Jacobian in the form of a tensor, a tuple, or a nested tuple depending upon the nesting
+        structure of measurements in the original circuit.
 
     This transform supports analytic gradients of Gaussian CV operations using
     the parameter-shift rule. This gradient method returns *exact* gradients,
@@ -646,7 +641,9 @@ def param_shift_cv(
     .. details::
         :title: Usage Details
 
-        This gradient transform can be applied directly to :class:`QNode <pennylane.QNode>` objects:
+        This gradient transform can be applied directly to :class:`QNode <pennylane.QNode>` objects.
+        However, for performance reasons, we recommend providing the gradient transform as the ``diff_method`` argument
+        of the QNode decorator, and differentiating with your preferred machine learning framework.
 
         >>> @qml.qnode(dev)
         ... def circuit(params):
diff --git a/pennylane/gradients/parameter_shift_hessian.py b/pennylane/gradients/parameter_shift_hessian.py
index 6747529aa..89eeaa96b 100644
--- a/pennylane/gradients/parameter_shift_hessian.py
+++ b/pennylane/gradients/parameter_shift_hessian.py
@@ -396,7 +396,7 @@ def _contract_qjac_with_cjac(qhess, cjac, tape):
 def param_shift_hessian(
     tape: qml.tape.QuantumTape, argnum=None, diagonal_shifts=None, off_diagonal_shifts=None, f0=None
 ) -> (Sequence[qml.tape.QuantumTape], Callable):
-    r"""Transform a QNode to compute the parameter-shift Hessian with respect to its trainable
+    r"""Transform a circuit to compute the parameter-shift Hessian with respect to its trainable
     parameters. This is the Hessian transform to replace the old one in the new return types system
 
     Use this transform to explicitly generate and explore parameter-shift circuits for computing
@@ -408,7 +408,7 @@ def param_shift_hessian(
     >>> qml.jacobian(qml.grad(cost))(weights)
 
     Args:
-        tape (pennylane.QNode or .QuantumTape): quantum tape or QNode to differentiate
+        tape (QNode or QuantumTape): quantum circuit to differentiate
         argnum (int or list[int] or array_like[bool] or None): Parameter indices to differentiate
             with respect to. If not provided, the Hessian with respect to all
             trainable indices is returned. Note that the indices refer to tape
@@ -432,18 +432,13 @@ def param_shift_hessian(
             instead of evaluating the input tape, reducing the number of device invocations.
 
     Returns:
-        function or tuple[list[QuantumTape], function]:
+        qnode (QNode) or tuple[List[QuantumTape], function]:
 
-        - If the input is a QNode, an object representing the Hessian (function) of
-          the QNode that can be executed to obtain the Hessian matrix.
-          The returned Hessian matrix is given as a tensor or nested tuples of tensors.
-          The level of nesting depends on the number of trainable QNode arguments, the output
-          shape(s) of the input QNode itself, and the usage of shot vectors in the QNode execution.
+        The transformed circuit as described in :func:`qml.transform <pennylane.transform>`. Executing this circuit
+        will provide the Hessian in the form of a tensor, a tuple, or a nested tuple depending upon the number
+        of trainable QNode arguments, the output shape(s) of the input QNode itself, and the usage of shot vectors
+        in the QNode execution.
 
-        - If the input is a tape, a tuple containing a
-          list of generated tapes, together with a post-processing
-          function to be applied to the results of the evaluated tapes
-          in order to obtain the Hessian matrix.
 
         Note: By default a QNode with the keyword ``hybrid=True`` computes derivates with respect to
         QNode arguments, which can include classical computations on those arguments before they are
@@ -453,7 +448,9 @@ def param_shift_hessian(
 
     **Example**
 
-    Applying the Hessian transform to a QNode computes its Hessian tensor:
+    Applying the Hessian transform to a QNode computes its Hessian tensor.
+    This works best if no classical processing is applied within the
+    QNode to operation parameters.
 
     >>> dev = qml.device("default.qubit", wires=2)
     >>> @qml.qnode(dev)
diff --git a/pennylane/gradients/pulse_gradient.py b/pennylane/gradients/pulse_gradient.py
index 2693d10b6..f6a20ecc8 100644
--- a/pennylane/gradients/pulse_gradient.py
+++ b/pennylane/gradients/pulse_gradient.py
@@ -22,7 +22,7 @@ import numpy as np
 
 import pennylane as qml
 from pennylane.pulse import ParametrizedEvolution, HardwareHamiltonian
-from pennylane.transforms.core import transform
+from pennylane import transform
 
 from .parameter_shift import _make_zero_rep
 from .general_shift_rules import eigvals_to_frequencies, generate_shift_rule
@@ -334,7 +334,7 @@ def stoch_pulse_grad(
     of the envelopes :math:`\partial f_j / \partial v_k` at the sampled times suitably.
 
     Args:
-        tape (pennylane.QNode or .QuantumTape): quantum tape or QNode to differentiate
+        tape (QuantumTape): quantum circuit to differentiate
         argnum (int or list[int] or None): Trainable tape parameter indices to differentiate
             with respect to. If not provided, the derivatives with respect to all
             trainable parameters are returned.
@@ -348,17 +348,11 @@ def stoch_pulse_grad(
             tapes is created, increasing performance on simulators.
 
     Returns:
-        function or tuple[list[QuantumTape], function]:
+        tuple[List[QuantumTape], function]:
 
-        - If the input is a QNode, an object representing the Jacobian (function) of the QNode
-          that can be executed to obtain the Jacobian.
-          The type of the Jacobian returned is either a tensor, a tuple or a
-          nested tuple depending on the nesting structure of the original QNode output.
-
-        - If the input is a tape, a tuple containing a
-          list of generated tapes, together with a post-processing
-          function to be applied to the results of the evaluated tapes
-          in order to obtain the Jacobian.
+        The transformed circuit as described in :func:`qml.transform <pennylane.transform>`. Executing this circuit
+        will provide the Jacobian in the form of a tensor, a tuple, or a nested tuple depending upon the nesting
+        structure of measurements in the original circuit.
 
     This transform realizes the stochastic parameter-shift rule for pulse sequences, as introduced
     in `Banchi and Crooks (2018) <https://quantum-journal.org/papers/q-2021-01-25-386/>`_ and
diff --git a/pennylane/gradients/pulse_gradient_odegen.py b/pennylane/gradients/pulse_gradient_odegen.py
index 39dc815f5..9ead08b3e 100644
--- a/pennylane/gradients/pulse_gradient_odegen.py
+++ b/pennylane/gradients/pulse_gradient_odegen.py
@@ -24,7 +24,7 @@ import pennylane as qml
 
 from pennylane.pulse import ParametrizedEvolution
 from pennylane.ops.qubit.special_unitary import pauli_basis_strings, _pauli_decompose
-from pennylane.transforms.core import transform
+from pennylane import transform
 
 from .parameter_shift import _make_zero_rep
 from .pulse_gradient import _assert_has_jax, raise_pulse_diff_on_qnode
@@ -403,7 +403,7 @@ def _expval_pulse_odegen(tape, argnum, atol):
 def pulse_odegen(
     tape: qml.tape.QuantumTape, argnum=None, atol=1e-7
 ) -> (Sequence[qml.tape.QuantumTape], Callable):
-    r"""Transform a QNode to compute the pulse generator parameter-shift gradient of pulses
+    r"""Transform a circuit to compute the pulse generator parameter-shift gradient of pulses
     in a pulse program with respect to their inputs.
     This method combines automatic differentiation of few-qubit operations with
     hardware-compatible shift rules.
@@ -428,7 +428,7 @@ def pulse_odegen(
     See the theoretical background section below for more details.
 
     Args:
-        tape (pennylane.QNode or .QuantumTape): quantum tape or QNode to differentiate
+        tape (QuantumTape): quantum circuit to differentiate
         argnum (int or list[int] or None): Trainable tape parameter indices to differentiate
             with respect to. If not provided, the derivatives with respect to all
             trainable parameters are returned.
@@ -437,17 +437,11 @@ def pulse_odegen(
             ``qml.math.isclose(x, 0., atol=atol, rtol=0) == True`` are neglected.
 
     Returns:
-        function or tuple[list[QuantumTape], function]:
+        tuple[List[QuantumTape], function]:
 
-        - If the input is a QNode, an object representing the Jacobian (function) of the QNode
-          that can be executed to obtain the Jacobian.
-          The type of the Jacobian returned is either a tensor, a tuple or a
-          nested tuple depending on the nesting structure of the original QNode output.
-
-        - If the input is a tape, a tuple containing a
-          list of generated tapes, together with a post-processing
-          function to be applied to the results of the evaluated tapes
-          in order to obtain the Jacobian.
+        The transformed circuit as described in :func:`qml.transform <pennylane.transform>`. Executing this circuit
+        will provide the Jacobian in the form of a tensor, a tuple, or a nested tuple depending upon the nesting
+        structure of measurements in the original circuit.
 
     .. note::
 
diff --git a/pennylane/gradients/spsa_gradient.py b/pennylane/gradients/spsa_gradient.py
index 45b94da65..18938ccdd 100644
--- a/pennylane/gradients/spsa_gradient.py
+++ b/pennylane/gradients/spsa_gradient.py
@@ -22,7 +22,7 @@ from functools import partial
 import numpy as np
 
 import pennylane as qml
-from pennylane.transforms.core import transform
+from pennylane import transform
 from pennylane.gradients.gradient_transform import _contract_qjac_with_cjac
 from pennylane.transforms.tape_expand import expand_invalid_trainable
 
@@ -103,13 +103,13 @@ def spsa_grad(
     sampler=_rademacher_sampler,
     sampler_rng=None,
 ) -> (Sequence[qml.tape.QuantumTape], Callable):
-    r"""Transform a QNode to compute the SPSA gradient of all gate
+    r"""Transform a circuit to compute the SPSA gradient of all gate
     parameters with respect to its inputs. This estimator shifts all parameters
     simultaneously and approximates the gradient based on these shifts and a
     finite-difference method.
 
     Args:
-        tape (pennylane.QNode or .QuantumTape): quantum tape or QNode to differentiate
+        tape (QNode or QuantumTape): quantum circuit to differentiate
         argnum (int or list[int] or None): Trainable parameter indices to differentiate
             with respect to. If not provided, the derivatives with respect to all
             trainable parameters are returned.
@@ -166,17 +166,11 @@ def spsa_grad(
             ``spsa_grad`` in each call.
 
     Returns:
-        function or tuple[list[QuantumTape], function]:
+        qnode (QNode) or tuple[List[QuantumTape], function]:
 
-        - If the input is a QNode, an object representing the Jacobian (function) of the QNode
-          that can be executed to obtain the Jacobian.
-          The type of the Jacobian returned is either a tensor, a tuple or a
-          nested tuple depending on the nesting structure of the original QNode output.
-
-        - If the input is a tape, a tuple containing a
-          list of generated tapes, together with a post-processing
-          function to be applied to the results of the evaluated tapes
-          in order to obtain the Jacobian.
+        The transformed circuit as described in :func:`qml.transform <pennylane.transform>`. Executing this circuit
+        will provide the Jacobian in the form of a tensor, a tuple, or a nested tuple depending upon the nesting
+        structure of measurements in the original circuit.
 
     **Example**
 
diff --git a/pennylane/interfaces/execution.py b/pennylane/interfaces/execution.py
index 6a6a0b437..f5ec7165a 100644
--- a/pennylane/interfaces/execution.py
+++ b/pennylane/interfaces/execution.py
@@ -424,7 +424,7 @@ def execute(
         interface (str): The interface that will be used for classical autodifferentiation.
             This affects the types of parameters that can exist on the input tapes.
             Available options include ``autograd``, ``torch``, ``tf``, ``jax`` and ``auto``.
-        transform_program(qml.transforms.core.TransformProgram): A transform program to be applied to the initial tape.
+        transform_program(.TransformProgram): A transform program to be applied to the initial tape.
         config (qml.devices.ExecutionConfig): A datastructure describing the parameters needed to fully describe the execution.
         grad_on_execution (bool, str): Whether the gradients should be computed on the execution or not. Only applies
             if the device is queried for the gradient; gradient transform
diff --git a/pennylane/interfaces/jacobian_products.py b/pennylane/interfaces/jacobian_products.py
index 241f6a685..e0a259c0e 100644
--- a/pennylane/interfaces/jacobian_products.py
+++ b/pennylane/interfaces/jacobian_products.py
@@ -173,12 +173,12 @@ class JacobianProductCalculator(abc.ABC):
 
 
 class TransformJacobianProducts(JacobianProductCalculator):
-    """Compute VJPs, JVPs and Jacobians via a :class:`~.gradient_transform`.
+    """Compute VJPs, JVPs and Jacobians via a gradient transform :class:`~.TransformDispatcher`.
 
     Args:
         inner_execute (Callable[[Tuple[QuantumTape]], ResultBatch]): a function that
             executes the batch of circuits and returns their results.
-        gradient_transform (pennylane.gradients.gradient_transform): the gradient transform to use.
+        gradient_transform (.TransformDispatcher): the gradient transform to use.
         gradient_kwargs (dict): Any keyword arguments for the gradient transform.
 
     >>> inner_execute = qml.device('default.qubit').execute
@@ -194,7 +194,7 @@ class TransformJacobianProducts(JacobianProductCalculator):
     def __init__(
         self,
         inner_execute: Callable,
-        gradient_transform: "qml.gradients.gradient_transform",
+        gradient_transform: "pennylane.transforms.core.TransformDispatcher",
         gradient_kwargs: Optional[dict] = None,
     ):
         if logger.isEnabledFor(logging.DEBUG):  # pragma: no cover
diff --git a/pennylane/ops/functions/eigvals.py b/pennylane/ops/functions/eigvals.py
index 4201e38d2..48f8938f0 100644
--- a/pennylane/ops/functions/eigvals.py
+++ b/pennylane/ops/functions/eigvals.py
@@ -23,7 +23,7 @@ import scipy
 
 import pennylane as qml
 from pennylane.transforms.op_transforms import OperationTransformError
-from pennylane.transforms.core import transform
+from pennylane import transform
 from pennylane.typing import TensorLike
 
 
@@ -41,7 +41,7 @@ def eigvals(op: qml.operation.Operator, k=1, which="SA") -> TensorLike:
         `documentation <https://docs.scipy.org/doc/scipy/reference/generated/scipy.sparse.linalg.eigsh.html#scipy.sparse.linalg.eigsh>`_.
 
     Args:
-        op (.Operator or .QuantumTape): A quantum operator or tape.
+        op (Operator or QNode or QuantumTape or Callable): A quantum operator or quantum circuit.
         k (int): The number of eigenvalues to be returned for a :class:`~.SparseHamiltonian`.
         which (str): Method for computing the eigenvalues of a :class:`~.SparseHamiltonian`. The
             possible methods are ``'LM'`` (largest in magnitude), ``'SM'`` (smallest in magnitude),
@@ -49,10 +49,11 @@ def eigvals(op: qml.operation.Operator, k=1, which="SA") -> TensorLike:
             from each end of the spectrum).
 
     Returns:
-        TensorLike or (Sequence[.QuantumTape], Callable): If an operator is provided as input, the eigenvalues
-        are returned directly. If a quantum tape is provided as input, a list of transformed tapes and a post-processing
-        function are returned. When called, this function will return the unitary matrix in the appropriate autodiff
-        framework (Autograd, TensorFlow, PyTorch, JAX) given its parameters.
+        TensorLike or qnode (QNode) or quantum function (Callable) or tuple[List[QuantumTape], function]:
+
+        If an operator is provided as input, the eigenvalues are returned directly in the form of a tensor.
+        Otherwise, the transformed circuit is returned as described in :func:`qml.transform <pennylane.transform>`.
+        Executing this circuit will provide the eigenvalues as a tensor.
 
     **Example**
 
diff --git a/pennylane/ops/functions/map_wires.py b/pennylane/ops/functions/map_wires.py
index 60848d209..f13eb40a1 100644
--- a/pennylane/ops/functions/map_wires.py
+++ b/pennylane/ops/functions/map_wires.py
@@ -23,7 +23,7 @@ from pennylane.operation import Operator
 from pennylane.qnode import QNode
 from pennylane.queuing import QueuingManager
 from pennylane.tape import QuantumScript, QuantumTape
-from pennylane.transforms.core import transform
+from pennylane import transform
 
 
 def map_wires(
@@ -36,15 +36,16 @@ def map_wires(
     wire map.
 
     Args:
-        input (.Operator, pennylane.QNode, .QuantumTape, or Callable): an operator, quantum node,
-            quantum tape, or function that applies quantum operations
+        input (Operator or QNode or QuantumTape or Callable): an operator or a quantum circuit.
         wire_map (dict): dictionary containing the old wires as keys and the new wires as values
         queue (bool): Whether or not to queue the object when recording. Defaults to False.
         replace (bool): When ``queue=True``, if ``replace=True`` the input operators will be
             replaced by its mapped version. Defaults to False.
 
     Returns:
-        (.Operator, pennylane.QNode, .QuantumTape, or Callable): input with changed wires
+        operator (Operator) or qnode (QNode) or quantum function (Callable) or tuple[List[.QuantumTape], function]:
+
+        The transformed circuit or operator with updated wires in :func:`qml.transform <pennylane.transform>`.
 
     .. note::
 
diff --git a/pennylane/ops/functions/matrix.py b/pennylane/ops/functions/matrix.py
index 28c5f3e2a..fa9ce1422 100644
--- a/pennylane/ops/functions/matrix.py
+++ b/pennylane/ops/functions/matrix.py
@@ -20,7 +20,7 @@ from functools import partial
 
 import pennylane as qml
 from pennylane.transforms.op_transforms import OperationTransformError
-from pennylane.transforms.core import transform
+from pennylane import transform
 from pennylane.typing import TensorLike
 
 
@@ -28,15 +28,16 @@ def matrix(op: qml.operation.Operator, wire_order=None) -> TensorLike:
     r"""The matrix representation of an operation or quantum circuit.
 
     Args:
-        op (.Operator or .QuantumTape): A quantum operator or tape.
+        op (Operator or QNode or QuantumTape or Callable): A quantum operator or quantum circuit.
         wire_order (Sequence[Any], optional): Order of the wires in the quantum circuit.
             Defaults to the order in which the wires appear in the quantum function.
 
     Returns:
-        TensorLike or (Sequence[.QuantumTape], Callable): If an operator is provided as input, the matrix
-        is returned directly. If a quantum tape is provided, a list of transformed tapes and a post-processing
-        function are returned. When called, this function will return unitary matrix in the appropriate
-        autodiff framework (Autograd, TensorFlow, PyTorch, JAX) given its parameters.
+        TensorLike or qnode (QNode) or quantum function (Callable) or tuple[List[QuantumTape], function]:
+
+        If an operator is provided as input, the matrix is returned directly in the form of a tensor.
+        Otherwise, the transformed circuit is returned as described in :func:`qml.transform <pennylane.transform>`.
+        Executing this circuit will provide its matrix representation.
 
     **Example**
 
diff --git a/pennylane/optimize/adaptive.py b/pennylane/optimize/adaptive.py
index c4edced9a..bf42b17f1 100644
--- a/pennylane/optimize/adaptive.py
+++ b/pennylane/optimize/adaptive.py
@@ -19,7 +19,7 @@ from typing import Sequence, Callable
 import pennylane as qml
 from pennylane import numpy as np
 from pennylane.tape import QuantumTape
-from pennylane.transforms.core import transform
+from pennylane import transform
 
 
 @transform
@@ -27,16 +27,13 @@ def append_gate(tape: QuantumTape, params, gates) -> (Sequence[QuantumTape], Cal
     """Append parameterized gates to an existing tape.
 
     Args:
-        tape (QuantumTape): quantum tape to transform by adding gates
+        tape (QuantumTape or QNode or Callable): quantum circuit to transform by adding gates
         params (array[float]): parameters of the gates to be added
         gates (list[Operator]): list of the gates to be added
 
     Returns:
-        pennylane.QNode or qfunc or tuple[List[.QuantumTape], function]: If a QNode is passed,
-        it returns a QNode with the transform added to its transform program.
-        If a tape is passed, returns a tuple containing a list of
-        quantum tapes to be evaluated, and a function to be applied to these
-        tape executions.
+        qnode (QNode) or quantum function (Callable) or tuple[List[QuantumTape], function]: The transformed circuit as described in :func:`qml.transform <pennylane.transform>`.
+
     """
     new_operations = []
 
diff --git a/pennylane/optimize/riemannian_gradient.py b/pennylane/optimize/riemannian_gradient.py
index 4f69c8fdc..2ae06b7f7 100644
--- a/pennylane/optimize/riemannian_gradient.py
+++ b/pennylane/optimize/riemannian_gradient.py
@@ -19,7 +19,7 @@ import numpy as np
 from scipy.sparse.linalg import expm
 import pennylane as qml
 
-from pennylane.transforms.core import transform
+from pennylane import transform
 from pennylane.tape import QuantumTape
 from pennylane.queuing import QueuingManager
 
@@ -56,17 +56,14 @@ def append_time_evolution(
     and append this unitary.
 
     Args:
-        tape (QuantumTape or .QNode): circuit to transform.
+        tape (QuantumTape or QNode or Callable): circuit to transform.
         riemannian_gradient (.Hamiltonian): Hamiltonian object representing the Riemannian gradient.
         t (float): time evolution parameter.
         n (int): number of Trotter steps.
 
     Returns:
-        pennylane.QNode or qfunc or tuple[List[.QuantumTape], function]: If a QNode is passed,
-        it returns a QNode with the transform added to its transform program.
-        If a tape is passed, returns a tuple containing a list of
-        quantum tapes to be evaluated, and a function to be applied to these
-        tape executions.
+        qnode (QNode) or quantum function (Callable) or tuple[List[QuantumTape], function]: The transformed circuit as described in :func:`qml.transform <pennylane.transform>`.
+
 
     """
     new_operations = tape.operations
diff --git a/pennylane/qinfo/transforms.py b/pennylane/qinfo/transforms.py
index ebf7c762d..4e2f0703c 100644
--- a/pennylane/qinfo/transforms.py
+++ b/pennylane/qinfo/transforms.py
@@ -21,7 +21,7 @@ from pennylane.tape import QuantumTape
 from pennylane.devices import DefaultQubit, DefaultQubitLegacy, DefaultMixed
 from pennylane.measurements import StateMP, DensityMatrixMP
 from pennylane.transforms import adjoint_metric_tensor, metric_tensor
-from pennylane.transforms.core import transform
+from pennylane import transform
 
 
 @partial(transform, final_transform=True)
@@ -30,14 +30,14 @@ def reduced_dm(tape: QuantumTape, wires, **kwargs) -> (Sequence[QuantumTape], Ca
     :func:`~pennylane.state`.
 
     Args:
-        tape (QuantumTape): A :class:`~.QuantumTape` returning :func:`~pennylane.state`.
+        tape (QuantumTape or QNode or Callable)): A quantum circuit returning :func:`~pennylane.state`.
         wires (Sequence(int)): List of wires in the considered subsystem.
 
     Returns:
-        pennylane.QNode or qfunc or tuple[List[.QuantumTape], Callable]: If a QNode
-        is passed, it returns a QNode with the transform added to its transform program.
-        If a tape is passed, returns a tuple containing a list of quantum tapes to be
-        evaluated, and a function to be applied to these tape executions.
+        qnode (QNode) or quantum function (Callable) or tuple[List[QuantumTape], function]:
+
+        The transformed circuit as described in :func:`qml.transform <pennylane.transform>`. Executing this circuit
+        will provide the reduced density matrix in the form of a tensor.
 
     **Example**
 
@@ -119,14 +119,14 @@ def purity(tape: QuantumTape, wires, **kwargs) -> (Sequence[QuantumTape], Callab
     the overall state, include all wires in the ``wires`` argument.
 
     Args:
-        tape (pennylane.tape.QuantumTape): A :class:`.QuantumTape` objeect returning a :func:`~pennylane.state`.
+        tape (QNode or QuantumTape or Callable): A quantum circuit object returning a :func:`~pennylane.state`.
         wires (Sequence(int)): List of wires in the considered subsystem.
 
     Returns:
-        pennylane.QNode or qfunc or tuple[List[.QuantumTape], Callable]: If a QNode
-        is passed, it returns a QNode with the transform added to its transform program.
-        If a tape is passed, returns a tuple containing a list of quantum tapes to be
-        evaluated, and a function to be applied to these tape executions.
+        qnode (QNode) or quantum function (Callable) or tuple[List[.QuantumTape], function]:
+
+        The transformed circuit as described in :func:`qml.transform <pennylane.transform>`. Executing this circuit
+        will provide the purity in the form of a tensor.
 
     **Example**
 
@@ -211,15 +211,15 @@ def vn_entropy(
         S( \rho ) = -\text{Tr}( \rho \log ( \rho ))
 
     Args:
-        tape (.QuantumTape): A :class:`.QuantumTape` returning a :func:`~pennylane.state`.
+        tape (QNode or QuantumTape or Callable): A quantum circuit returning a :func:`~pennylane.state`.
         wires (Sequence(int)): List of wires in the considered subsystem.
         base (float): Base for the logarithm, default is None the natural logarithm is used in this case.
 
     Returns:
-        pennylane.QNode or qfunc or tuple[List[.QuantumTape], Callable]: If a QNode
-        is passed, it returns a QNode with the transform added to its transform program.
-        If a tape is passed, returns a tuple containing a list of quantum tapes to be
-        evaluated, and a function to be applied to these tape executions.
+        qnode (QNode) or quantum function (Callable) or tuple[List[QuantumTape], function]:
+
+        The transformed circuit as described in :func:`qml.transform <pennylane.transform>`. Executing this circuit
+        will provide the Von Neumann entropy in the form of a tensor.
 
     **Example**
 
@@ -312,16 +312,16 @@ def mutual_info(
     one system by measuring the other system.
 
     Args:
-        qnode (QNode): A :class:`.QNode` returning a :func:`~pennylane.state`.
+        qnode (QNode or QuantumTape or Callable): A quantum circuit returning a :func:`~pennylane.state`.
         wires0 (Sequence(int)): List of wires in the first subsystem.
         wires1 (Sequence(int)): List of wires in the second subsystem.
         base (float): Base for the logarithm. If None, the natural logarithm is used.
 
     Returns:
-        pennylane.QNode or qfunc or tuple[List[.QuantumTape], Callable]: If a QNode
-        is passed, it returns a QNode with the transform added to its transform program.
-        If a tape is passed, returns a tuple containing a list of quantum tapes to be
-        evaluated, and a function to be applied to these tape executions.
+        qnode (QNode) or quantum function (Callable) or tuple[List[QuantumTape], function]:
+
+        The transformed circuit as described in :func:`qml.transform <pennylane.transform>`. Executing this circuit
+        will provide the mutual information in the form of a tensor.
 
     **Example**
 
@@ -666,11 +666,14 @@ def quantum_fisher(
         :func:`~.pennylane.metric_tensor`, :func:`~.pennylane.adjoint_metric_tensor`, :func:`~.pennylane.qinfo.transforms.classical_fisher`
 
     Args:
-        qnode (:class:`.QNode`): A :class:`.QNode` that may have arbitrary return types.
+        tape (QNode or QuantumTape or Callable): A quantum circuit that may have arbitrary return types.
         *args: In case finite shots are used, further arguments according to :func:`~.pennylane.metric_tensor` may be passed.
 
     Returns:
-        func: A function that computes the quantum fisher information matrix.
+        qnode (QNode) or quantum function (Callable) or tuple[List[QuantumTape], function]:
+
+        The transformed circuit as described in :func:`qml.transform <pennylane.transform>`. Executing this circuit
+        will provide the quantum Fisher information in the form of a tensor.
 
     .. note::
 
diff --git a/pennylane/qnode.py b/pennylane/qnode.py
index 63c0d2227..da36d7e2b 100644
--- a/pennylane/qnode.py
+++ b/pennylane/qnode.py
@@ -100,9 +100,9 @@ class QNode:
             * ``"auto"``: The QNode automatically detects the interface from the input values of
               the quantum function.
 
-        diff_method (str or .gradient_transform): The method of differentiation to use in the created QNode.
-            Can either be a :class:`~.gradient_transform`, which includes all quantum gradient
-            transforms in the :mod:`qml.gradients <.gradients>` module, or a string. The following
+        diff_method (str or .TransformDispatcher): The method of differentiation to use in
+            the created QNode. Can either be a :class:`~.TransformDispatcher`, which includes all
+            quantum gradient transforms in the :mod:`qml.gradients <.gradients>` module, or a string. The following
             strings are allowed:
 
             * ``"best"``: Best available method. Uses classical backpropagation or the
@@ -131,7 +131,6 @@ class QNode:
               rule for all supported quantum operation arguments. More info is in the documentation
               :func:`qml.gradients.hadamard_grad <.gradients.hadamard_grad>`.
 
-
             * ``"finite-diff"``: Uses numerical finite-differences for all quantum operation
               arguments.
 
@@ -525,16 +524,13 @@ class QNode:
 
     @property
     def transform_program(self):
-        """The transform program used by the QNode.
-
-        .. warning:: This is an experimental feature.
-        """
+        """The transform program used by the QNode."""
         return self._transform_program
 
     def add_transform(self, transform_container):
-        """Add a transform container to the transform program.
+        """Add a transform (container) to the transform program.
 
-        .. warning:: This is an experimental feature.
+        .. warning:: This is a developer facing feature and is called when a transform is applied on a QNode.
         """
         self._transform_program.push_back(transform_container=transform_container)
 
@@ -588,13 +584,13 @@ class QNode:
         Args:
             device (.Device): PennyLane device
             interface (str): name of the requested interface
-            diff_method (str or .gradient_transform): The requested method of differentiation.
+            diff_method (str or .TransformDispatcher): The requested method of differentiation.
                 If a string, allowed options are ``"best"``, ``"backprop"``, ``"adjoint"``,
                 ``"device"``, ``"parameter-shift"``, ``"hadamard"``, ``"finite-diff"``, or ``"spsa"``.
                 A gradient transform may also be passed here.
 
         Returns:
-            tuple[str or .gradient_transform, dict, .Device: Tuple containing the ``gradient_fn``,
+            tuple[str or .TransformDispatcher, dict, .Device: Tuple containing the ``gradient_fn``,
             ``gradient_kwargs``, and the device to use when calling the execute function.
         """
         if diff_method == "best":
@@ -657,7 +653,7 @@ class QNode:
             interface (str): name of the requested interface
 
         Returns:
-            tuple[str or .gradient_transform, dict, .Device: Tuple containing the ``gradient_fn``,
+            tuple[str or .TransformDispatcher, dict, .Device: Tuple containing the ``gradient_fn``,
             ``gradient_kwargs``, and the device to use when calling the execute function.
         """
         try:
diff --git a/pennylane/shadows/transforms.py b/pennylane/shadows/transforms.py
index f488a4795..89f7de94c 100644
--- a/pennylane/shadows/transforms.py
+++ b/pennylane/shadows/transforms.py
@@ -22,7 +22,7 @@ import pennylane as qml
 import pennylane.numpy as np
 from pennylane.measurements import ClassicalShadowMP
 from pennylane.tape import QuantumScript, QuantumTape
-from pennylane.transforms.core import transform
+from pennylane import transform
 
 
 @transform
@@ -54,19 +54,23 @@ def _replace_obs(tape: QuantumTape, obs, *args, **kwargs) -> (Sequence[QuantumTa
 
 @partial(transform, final_transform=True)
 def shadow_expval(tape: QuantumTape, H, k=1) -> (Sequence[QuantumTape], Callable):
-    """Transform a QNode returning a classical shadow into one that returns
+    """Transform a circuit returning a classical shadow into one that returns
     the approximate expectation values in a differentiable manner.
 
     See :func:`~.pennylane.shadow_expval` for more usage details.
 
     Args:
+        tape (QNode or QuantumTape or Callable): A quantum circuit.
         H (:class:`~.pennylane.Observable` or list[:class:`~.pennylane.Observable`]): Observables
             for which to compute the expectation values
         k (int): k (int): Number of equal parts to split the shadow's measurements to compute
             the median of means. ``k=1`` corresponds to simply taking the mean over all measurements.
 
     Returns:
-        tensor-like[float]: 1-D tensor containing the expectation value estimates for each observable
+        qnode (QNode) or quantum function (Callable) or tuple[List[QuantumTape], function]:
+
+        The transformed circuit as described in :func:`qml.transform <pennylane.transform>`. Executing this circuit
+        will provide the expectation value estimates for each observable in the form of a tensor.
 
     **Example**
 
@@ -75,7 +79,7 @@ def shadow_expval(tape: QuantumTape, H, k=1) -> (Sequence[QuantumTape], Callable
         H = qml.PauliZ(0) @ qml.PauliZ(1)
         dev = qml.device("default.qubit", wires=2, shots=10000)
 
-        @qml.shadows.shadow_expval(H, k=1)
+        @partial(qml.shadows.shadow_expval, H, k=1)
         @qml.qnode(dev)
         def circuit(x):
             qml.Hadamard(wires=0)
@@ -168,10 +172,11 @@ def _shadow_state_undiffable(tape, wires):
 
 @partial(transform, final_transform=True)
 def shadow_state(tape: QuantumTape, wires, diffable=False) -> (Sequence[QuantumTape], Callable):
-    """Transform a QNode returning a classical shadow into one that returns
+    """Transform a circuit returning a classical shadow into one that returns
     the reconstructed state in a differentiable manner.
 
     Args:
+        tape (QNode or QuantumTape or Callable): A quantum circuit.
         wires (list[int] or list[list[int]]): If a list of ints, this represents
             the wires over which to reconstruct the state. If a list of list of ints,
             a state is reconstructed for every element of the outer list, saving
@@ -182,7 +187,10 @@ def shadow_state(tape: QuantumTape, wires, diffable=False) -> (Sequence[QuantumT
             cost.
 
     Returns:
-        list[tensor-like[complex]]: The reconstructed states
+        qnode (QNode) or quantum function (Callable) or tuple[List[QuantumTape], function]:
+
+        The transformed circuit as described in :func:`qml.transform <pennylane.transform>`. Executing this circuit
+        will provide the reconstructed state in the form of a tensor.
 
     **Example**
 
@@ -190,7 +198,7 @@ def shadow_state(tape: QuantumTape, wires, diffable=False) -> (Sequence[QuantumT
 
         dev = qml.device("default.qubit", wires=2, shots=10000)
 
-        @qml.shadows.shadow_state(wires=[0, 1], diffable=True)
+        @partial(qml.shadows.shadow_state, wires=[0, 1], diffable=True)
         @qml.qnode(dev)
         def circuit(x):
             qml.Hadamard(wires=0)
diff --git a/pennylane/transforms/__init__.py b/pennylane/transforms/__init__.py
index f753322ce..4405fa58f 100644
--- a/pennylane/transforms/__init__.py
+++ b/pennylane/transforms/__init__.py
@@ -12,51 +12,30 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 """
-This subpackage contains QNode, quantum function, device, and tape transforms.
-
+This subpackage contains PennyLane transforms and their building blocks.
 
 .. currentmodule:: pennylane
 
-Transforms
-----------
-
-Transforms that act on QNodes
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Custom transforms
+-----------------
 
-These transforms accept QNodes, and return new transformed functions
-that compute the desired quantity.
+:func:`qml.transform <pennylane.transform>` can be used to define custom transformations
+that work with PennyLane QNodes; such transformations can map a circuit
+to one or many new circuits alongside associated classical post-processing.
 
 .. autosummary::
     :toctree: api
 
-    ~transforms.classical_jacobian
-    ~batch_params
-    ~batch_input
-    ~batch_partial
-    ~metric_tensor
-    ~adjoint_metric_tensor
-    ~specs
-    ~transforms.split_non_commuting
-
-Transforms that act on quantum functions
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-These transforms accept quantum functions (Python functions
-containing quantum operations) that are used to construct QNodes.
+    ~transforms.core.transform
 
-.. autosummary::
-    :toctree: api
-
-    ~transforms.cond
-    ~defer_measurements
-    ~apply_controlled_Q
-    ~quantum_monte_carlo
-    ~transforms.insert
+Transforms library
+------------------
+A range of ready-to-use transforms are available in PennyLane.
 
 Transforms for circuit compilation
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-This set of transforms accept quantum functions, and perform basic circuit compilation tasks.
+A set of transforms to perform basic circuit compilation tasks.
 
 .. autosummary::
     :toctree: api
@@ -137,26 +116,68 @@ There are also low-level functions that can be used to build up the circuit cutt
     ~transforms.qcut.place_wire_cuts
     ~transforms.qcut.find_and_place_cuts
 
-Transforms that act on tapes
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Transforms for error mitigation
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-These transforms accept quantum tapes, and return one or
-more tapes as well as a classical processing function.
+.. autosummary::
+    :toctree: api
+
+    ~transforms.mitigate_with_zne
+    ~transforms.fold_global
+    ~transforms.poly_extrapolate
+    ~transforms.richardson_extrapolate
+
+Other transforms
+~~~~~~~~~~~~~~~~
+
+These transforms use the :func:`pennylane.transform` function / decorator and can be used on
+:class:`pennylane.tape.QuantumTape`, :class:`pennylane.QNode`. They fulfill multiple purposes like circuit
+preprocessing, get information from a circuit and more.
 
 .. autosummary::
     :toctree: api
 
+    ~metric_tensor
+    ~adjoint_metric_tensor
+    ~batch_params
+    ~batch_input
+    ~transforms.insert
+    ~defer_measurements
+    ~transforms.split_non_commuting
     ~transforms.broadcast_expand
     ~transforms.hamiltonian_expand
     ~transforms.sign_expand
     ~transforms.sum_expand
+    ~transforms.convert_to_numpy_parameters
+    ~apply_controlled_Q
+    ~quantum_monte_carlo
 
-This transform accepts a single tape and returns a single tape:
+Transforms that act only on QNodes
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+These transforms only accept QNodes, and return new transformed functions
+that compute the desired quantity.
 
 .. autosummary::
     :toctree: api
 
-    ~transforms.convert_to_numpy_parameters
+    ~transforms.classical_jacobian
+    ~batch_partial
+    ~specs
+    ~draw
+    ~draw_mpl
+
+
+Transforms that act on quantum functions
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+These transforms accept quantum functions (Python functions
+containing quantum operations) that are used to construct QNodes.
+
+.. autosummary::
+    :toctree: api
+
+    ~transforms.cond
 
 Decorators and utility functions
 --------------------------------
@@ -167,10 +188,6 @@ to help build custom QNode, quantum function, and tape transforms:
 .. autosummary::
     :toctree: api
 
-    ~single_tape_transform
-    ~batch_transform
-    ~qfunc_transform
-    ~op_transform
     ~transforms.make_tape
     ~transforms.map_batch_transform
     ~transforms.create_expand_fn
@@ -181,28 +198,38 @@ to help build custom QNode, quantum function, and tape transforms:
     ~transforms.expand_trainable_multipar
     ~transforms.expand_nonunitary_gen
 
-Transforms for error mitigation
--------------------------------
+Transforms developer functions
+------------------------------
+
+:class:`~.TransformContainer`, :class:`~.TransformDispatcher` and  :class:`~.TransformProgram` are
+developer-facing objects that allow the
+creation, dispatching and composability of transforms. If you would like to make a custom transform, refer
+instead to the documentation of :func:`qml.transform <pennylane.transform>`.
 
 .. autosummary::
     :toctree: api
 
-    ~transforms.mitigate_with_zne
-    ~transforms.fold_global
-    ~transforms.poly_extrapolate
-    ~transforms.richardson_extrapolate
+    ~transforms.core.transform_dispatcher
+    ~transforms.core.transform_program
+
+Old transforms framework
+------------------------
 
-Transforms core
----------------
+These utility functions were previously used to create transforms in PennyLane and will be
+deprecated soon. It is now recommended to use :class:`qml.transform <pennylane.transform>`
+for creation of custom transforms.
 
 .. autosummary::
     :toctree: api
 
-    ~transforms.core.transform
-    ~transforms.core.transform_dispatcher
+    ~single_tape_transform
+    ~batch_transform
+    ~qfunc_transform
+    ~op_transform
 
 """
 # Import the decorators first to prevent circular imports when used in other transforms
+from .core import transform, TransformError
 from .batch_transform import batch_transform, map_batch_transform
 from .qfunc_transforms import make_tape, single_tape_transform, qfunc_transform
 from .op_transforms import op_transform
@@ -260,4 +287,3 @@ from . import qcut
 from .qcut import cut_circuit, cut_circuit_mc
 from .zx import to_zx, from_zx
 from .broadcast_expand import broadcast_expand
-from .core import transform, TransformError
diff --git a/pennylane/transforms/adjoint_metric_tensor.py b/pennylane/transforms/adjoint_metric_tensor.py
index 2897139ea..4047ec0eb 100644
--- a/pennylane/transforms/adjoint_metric_tensor.py
+++ b/pennylane/transforms/adjoint_metric_tensor.py
@@ -23,7 +23,7 @@ from pennylane import numpy as np
 
 # pylint: disable=too-many-statements,unused-argument
 from pennylane.transforms.metric_tensor import _contract_metric_tensor_with_cjac
-from pennylane.transforms.core import transform
+from pennylane.transforms import transform
 
 
 def _reshape_real_imag(state, dim):
@@ -80,11 +80,13 @@ def adjoint_metric_tensor(
           Note also that this makes the metric tensor strictly real-valued.
 
     Args:
-        tape (.QuantumTape): Circuit to compute the metric tensor of
+        tape (QNode or QuantumTape): Circuit to compute the metric tensor of
 
     Returns:
-        array: the metric tensor of the tape with respect to its trainable parameters.
-        Dimensions are ``(tape.num_params, tape.num_params)``.
+        qnode (QNode) or tuple[List[QuantumTape], function]:
+
+        The transformed circuit as described in :func:`qml.transform <pennylane.transform>`. Executing this circuit
+        will provide the metric tensor in the form of a tensor. Dimensions are ``(tape.num_params, tape.num_params)``.
 
     .. seealso:: :func:`~.metric_tensor` for hardware-compatible metric tensor computations.
 
diff --git a/pennylane/transforms/batch_input.py b/pennylane/transforms/batch_input.py
index 7effe8f56..ca21e1c67 100644
--- a/pennylane/transforms/batch_input.py
+++ b/pennylane/transforms/batch_input.py
@@ -28,7 +28,7 @@ def batch_input(
     argnum: Union[Sequence[int], int],
 ) -> (Sequence[QuantumTape], Callable):
     """
-    Transform a QNode to support an initial batch dimension for gate inputs.
+    Transform a circuit to support an initial batch dimension for gate inputs.
 
     In a classical ML application one needs to batch the non-trainable inputs of the network.
     This function executes the same analogue for a quantum circuit:
@@ -42,13 +42,15 @@ def batch_input(
     Based on `arXiv:2202.10471 <https://arxiv.org/abs/2202.10471>`__.
 
     Args:
-        tape (.QuantumTape or .QNode): Input quantum circuit to batch
+        tape (QNode or QuantumTape or Callable): Input quantum circuit to batch
         argnum (Sequence[int] or int): One or several index values indicating the position of the
             non-trainable batched parameters in the quantum tape.
 
     Returns:
-        Sequence[Sequence[.QuantumTape], Callable]: list of tapes arranged
-        according to unbatched inputs and a callable function to batch the results.
+        qnode (QNode) or quantum function (Callable) or tuple[List[QuantumTape], function]:
+
+        The transformed circuit as described in :func:`qml.transform <pennylane.transform>`. Executing this circuit
+        will provide the batched results.
 
     .. seealso:: :func:`~.batch_params`
 
diff --git a/pennylane/transforms/batch_params.py b/pennylane/transforms/batch_params.py
index 05dfe70fb..0c4f2a99b 100644
--- a/pennylane/transforms/batch_params.py
+++ b/pennylane/transforms/batch_params.py
@@ -102,14 +102,15 @@ def batch_params(
         the error.
 
     Args:
-        qnode (pennylane.QNode or .QuantumTape): quantum tape or QNode to add a batch dimension to
+        tape (QNode or QuantumTape or Callable): a quantum circuit to add a batch dimension to
         all_operations (bool): If ``True``, a batch dimension will be added to *all* operations
             in the QNode, rather than just trainable QNode parameters.
 
     Returns:
-        func: Function which accepts the same arguments as the QNode, however the
-        first dimension of each argument will be treated as a batch dimension.
-        The function output will also contain an initial batch dimension.
+        qnode (QNode) or quantum function (Callable) or tuple[List[QuantumTape], function]:
+
+        The transformed circuit as described in :func:`qml.transform <pennylane.transform>`. Executing this circuit
+        will provide the batched results, with the first dimension treated as the batch dimension.
 
     **Example**
 
diff --git a/pennylane/transforms/broadcast_expand.py b/pennylane/transforms/broadcast_expand.py
index 2309bb705..feada25e2 100644
--- a/pennylane/transforms/broadcast_expand.py
+++ b/pennylane/transforms/broadcast_expand.py
@@ -55,12 +55,14 @@ def broadcast_expand(tape: qml.tape.QuantumTape) -> (Sequence[qml.tape.QuantumTa
         Currently, not all templates have been updated to support broadcasting.
 
     Args:
-        tape (.QuantumTape): Broadcasted tape to be expanded
+        tape (QNode or QuantumTape or Callable): Broadcasted tape to be expanded
 
     Returns:
-        function or tuple[list[.QuantumTape], function]:
+        qnode (QNode) or quantum function (Callable) or tuple[List[QuantumTape], function]:
 
-        - If the input is a QNode, an object resembling the (broadcasted) input QNode
+        The transformed circuit as described in :func:`qml.transform <pennylane.transform>`.
+
+        - If the input is a QNode, the broadcasted input QNode
           that computes the QNode output serially with multiple circuit evaluations and
           stacks (and squeezes) the results into one batch of results.
 
diff --git a/pennylane/transforms/commutation_dag.py b/pennylane/transforms/commutation_dag.py
index 383df0497..e15a3e813 100644
--- a/pennylane/transforms/commutation_dag.py
+++ b/pennylane/transforms/commutation_dag.py
@@ -25,7 +25,7 @@ from networkx.drawing.nx_pydot import to_pydot
 import pennylane as qml
 from pennylane.tape import QuantumTape
 from pennylane.wires import Wires
-from pennylane.transforms.core import transform
+from pennylane.transforms import transform
 
 
 @partial(transform, is_informative=True)
@@ -39,16 +39,21 @@ def commutation_dag(tape: QuantumTape) -> (Sequence[QuantumTape], Callable):
     operations can be moved next to each other by pairwise commutation.
 
     Args:
-        tape ( .QuantumTape): The quantum circuit.
+        tape (QNode or QuantumTape or Callable): The quantum circuit.
 
     Returns:
-         function: Function which accepts the same arguments as the :class:`qml.QNode`, :class:`qml.tape.QuantumTape`
-         or quantum function. When called, this function will return the commutation DAG representation of the circuit.
+        qnode (QNode) or quantum function (Callable) or tuple[List[QuantumTape], function]:
+
+        The transformed circuit as described in :func:`qml.transform <pennylane.transform>`. Executing this circuit
+        will provide the commutation DAG.
 
     **Example**
 
+    >>> dev = qml.device("default.qubit")
+
     .. code-block:: python
 
+        @qml.qnode(device=dev)
         def circuit(x, y, z):
             qml.RX(x, wires=0)
             qml.RX(y, wires=0)
diff --git a/pennylane/transforms/compile.py b/pennylane/transforms/compile.py
index 20f6e70f9..0b11d11f5 100644
--- a/pennylane/transforms/compile.py
+++ b/pennylane/transforms/compile.py
@@ -47,7 +47,7 @@ def compile(
       (:func:`~pennylane.transforms.merge_rotations`)
 
     Args:
-        qfunc (function): A quantum function.
+        tape (QNode or QuantumTape or Callable): A quantum circuit.
         pipeline (list[single_tape_transform, qfunc_transform]): A list of
             tape and/or quantum function transforms to apply.
         basis_set (list[str]): A list of basis gates. When expanding the tape,
@@ -62,14 +62,36 @@ def compile(
             for tape expansion into the basis gates.
 
     Returns:
-        pennylane.QNode or qfunc or tuple[List[.QuantumTape], function]: If a QNode is passed,
-        it returns a QNode with the transform added to its transform program.
-        If a tape is passed, returns a tuple containing a list of
-        quantum tapes to be evaluated, and a function to be applied to these
-        tape executions.
+        qnode (QNode) or quantum function (Callable) or tuple[List[QuantumTape], function]: The compiled circuit. The output type is explained in :func:`qml.transform <pennylane.transform>`.
 
     **Example**
 
+    >>> dev = qml.device('default.qubit', wires=[0, 1, 2])
+
+    You can apply the transform directly on a :class:`QNode`:
+
+    .. code-block:: python
+
+        @compile
+        @qml.qnode(device=dev)
+        def circuit(x, y, z):
+            qml.Hadamard(wires=0)
+            qml.Hadamard(wires=1)
+            qml.Hadamard(wires=2)
+            qml.RZ(z, wires=2)
+            qml.CNOT(wires=[2, 1])
+            qml.RX(z, wires=0)
+            qml.CNOT(wires=[1, 0])
+            qml.RX(x, wires=0)
+            qml.CNOT(wires=[1, 0])
+            qml.RZ(-z, wires=2)
+            qml.RX(y, wires=2)
+            qml.PauliY(wires=2)
+            qml.CY(wires=[1, 2])
+            return qml.expval(qml.PauliZ(wires=0))
+
+    The default compilation pipeline is applied before execution.
+
     Consider the following quantum function:
 
     .. code-block:: python
@@ -92,7 +114,6 @@ def compile(
 
     Visually, the original function looks like this:
 
-    >>> dev = qml.device('default.qubit', wires=[0, 1, 2])
     >>> qnode = qml.QNode(qfunc, dev)
     >>> print(qml.draw(qnode)(0.2, 0.3, 0.4))
     0: ──H──RX(0.40)────╭X──────────RX(0.20)─╭X────┤  <Z>
@@ -102,7 +123,7 @@ def compile(
     We can compile it down to a smaller set of gates using the ``qml.compile``
     transform.
 
-    >>> compiled_qfunc = qml.compile()(qfunc)
+    >>> compiled_qfunc = qml.compile(qfunc)
     >>> compiled_qnode = qml.QNode(compiled_qfunc, dev)
     >>> print(qml.draw(compiled_qnode)(0.2, 0.3, 0.4))
     0: ──H──RX(0.60)─────────────────┤  <Z>
@@ -119,8 +140,8 @@ def compile(
 
         compiled_qfunc = qml.compile(
             pipeline=[
-                qml.transforms.commute_controlled(direction="left"),
-                qml.transforms.merge_rotations(atol=1e-6),
+                partial(qml.transforms.commute_controlled, direction="left"),
+                partial(qml.transforms.merge_rotations, atol=1e-6),
                 qml.transforms.cancel_inverses
             ],
             basis_set=["CNOT", "RX", "RY", "RZ"],
diff --git a/pennylane/transforms/core/transform.py b/pennylane/transforms/core/transform.py
index c656ca97a..3e327ed03 100644
--- a/pennylane/transforms/core/transform.py
+++ b/pennylane/transforms/core/transform.py
@@ -12,7 +12,8 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 """
-This module contains the transform function to make your custom transforms compatible with qfunc and QNodes.
+This module contains the transform function/decorator to make your custom transforms compatible with tapes, quantum
+functions and QNodes.
 """
 from typing import get_type_hints, Sequence, List, Tuple, Callable
 import pennylane as qml
@@ -26,39 +27,49 @@ def transform(
     is_informative=None,
     final_transform=False,
 ):
-    """The transform function is to be used to validate and dispatch a quantum transform on PennyLane objects (tape,
-    qfunc and Qnode). It can be used directly as a decorator on qfunc and qnodes.
+    """Generalizes a function that transforms tapes to work with additional circuit-like objects such as a
+    :class:`~.QNode`.
 
-    Args:
-        quantum_transform (callable): A quantum transform is defined as a function that has the following requirements:
-
-            * A quantum transform is a function that takes a quantum tape as first input and returns a sequence of tapes
-              and a processing function.
-
-            * The transform must have type hinting of the following form: my_quantum_transform(tape:
-              qml.tape.QuantumTape, ...) -> ( Sequence[qml.tape.QuantumTape], callable)
+    ``transform`` should be applied to a function that transforms tapes. Once validated, the result will
+    be an object that is able to transform PennyLane's range of circuit-like objects:
+    :class:`~.QuantumTape`, quantum function and :class:`~.QNode`.
+    A circuit-like object can be transformed either via decoration or by passing it functionally through
+    the created transform.
 
-        expand_transform (callable): An expand transform is defined as a function that has the following requirements:
+    Args:
+        quantum_transform (Callable): The input quantum transform must be a function that satisfies the
+            following requirements:
 
-            * An expand transform is a function that is applied before applying the defined quantum transform. It
-              takes the same arguments as the transform and returns a single tape in a sequence with a dummy processing
-              function.
+            * Accepts a :class:`~.QuantumTape` as its first input and
+              returns a sequence of :class:`~.QuantumTape` and a processing function.
 
-            * The expand transform must have the same type hinting as a quantum transform.
+            * The transform must have type hinting of the following form: ``my_quantum_transform(tape:
+              qml.tape.QuantumTape, ...) -> ( Sequence[qml.tape.QuantumTape], Callable)``
 
-        classical_cotransform (callable): A classical co-transform. NOT YET SUPPORTED.
+        expand_transform (Callable): An optional expand transform is applied directly before the input
+            quantum transform. It must be a function that satisfies the same requirements as
+            ``quantum_transform``.
+        classical_cotransform (Callable): A classical co-transform is a function to post-process the classical
+            jacobian and the quantum jacobian and has the signature: ``my_cotransform(qjac, cjac, tape) -> tensor_like``
         is_informative (bool): Whether or not a transform is informative. If true the transform is queued at the end
             of the transform program and the tapes or qnode aren't executed.
         final_transform (bool): Whether or not the transform is terminal. If true the transform is queued at the end
             of the transform program. ``is_informative`` supersedes ``final_transform``.
 
+    Returns:
+
+        .TransformDispatcher: Returns a transform dispatcher object that that can transform any
+        circuit-like object in PennyLane.
+
     **Example**
 
-    First define your quantum_transform, with the necessary type hinting defined above. In this example we copy the
+    First define an input quantum transform with the necessary type hinting defined above. In this example we copy the
     tape and sum the results of the execution of the two tapes.
 
     .. code-block:: python
 
+        from typing import Sequence, Callable
+
         def my_quantum_transform(tape: qml.tape.QuantumTape) -> (Sequence[qml.tape.QuantumTape], Callable):
             tape1 = tape
             tape2 = tape.copy()
@@ -68,41 +79,83 @@ def transform(
 
             return [tape1, tape2], post_processing_fn
 
-    Of course, we want to be able to apply this transform on ``qfunc`` and ``qnodes``. That's where the ``transform`` function
-    comes into play. This function validates the signature of your quantum transform and dispatches it on the different
-    object. Let's define a circuit as a qfunc and as a qnode.
+    We want to be able to apply this transform on both a ``qfunc`` and a :class:`pennylane.QNode` and will
+    use ``transform`` to achieve this. ``transform`` validates the signature of your input quantum transform
+    and makes it capable of transforming ``qfunc`` and :class:`pennylane.QNode` in addition to quantum tapes.
+    Let's define a circuit as a :class:`pennylane.QNode`:
 
-        .. code-block:: python
+    .. code-block:: python
 
-            def qfunc_circuit(a):
-                qml.Hadamard(wires=0)
-                qml.CNOT(wires=[0, 1])
-                qml.PauliX(wires=0)
-                qml.RZ(a, wires=1)
-                return qml.expval(qml.PauliZ(wires=0))
+        dev = qml.device("default.qubit")
 
-            dev = qml.device("default.qubit", wires=2)
+        @qml.qnode(device=dev)
+        def qnode_circuit(a):
+            qml.Hadamard(wires=0)
+            qml.CNOT(wires=[0, 1])
+            qml.PauliX(wires=0)
+            qml.RZ(a, wires=1)
+            return qml.expval(qml.PauliZ(wires=0))
 
-            @qml.qnode(device=dev)
-            def qnode_circuit(a):
-                qml.Hadamard(wires=0)
-                qml.CNOT(wires=[0, 1])
-                qml.PauliX(wires=0)
-                qml.RZ(a, wires=1)
-                return qml.expval(qml.PauliZ(wires=0))
+    We first apply ``transform`` to ``my_quantum_transform``:
 
     >>> dispatched_transform = transform(my_quantum_transform)
 
-    Now you can use the dispatched transform directly on qfunc and qnodes.
+    Now you can use the dispatched transform directly on a :class:`pennylane.QNode`.
+
+    For :class:`pennylane.QNode`, the dispatched transform populates the ``TransformProgram`` of your QNode. The
+    transform and its processing function are applied in the execution.
+
+    >>> transformed_qnode = dispatched_transform(qnode_circuit)
+    <QNode: wires=2, device='default.qubit', interface='auto', diff_method='best'>
+
+    >>> transformed_qnode.transform_program
+    TransformProgram(my_quantum_transform)
+
+    If we apply ``dispatched_transform`` a second time to the :class:`pennylane.QNode`, we would add
+    it to the transform program again and therefore the transform would be applied twice before execution.
+
+    >>> transformed_qnode = dispatched_transform(transformed_qnode)
+    >>> transformed_qnode.transform_program
+    TransformProgram(my_quantum_transform, my_quantum_transform)
+
+    When a transformed QNode is executed, the QNode's transform program is applied to the generated tape
+    and creates a sequence of tapes to be executed. The execution results are then post-processed in the
+    reverse order of the transform program to obtain the final results.
+
+    .. details::
+        :title: Signature of a transform
+
+        A dispatched transform is able to handle several PennyLane circuit-like objects:
+
+        - :class:`pennylane.QNode`
+        - a quantum function (callable)
+        - :class:`pennylane.tape.QuantumTape`
+        - :class:`pennylane.devices.Device`.
+
+        For each object, the transform will be applied in a different way, but it always preserves the underlying
+        tape-based quantum transform behaviour.
+
+        The return of a dispatched transform depends upon which of the above objects is passed as an input:
+
+        - For a :class:`~.QNode` input, the underlying transform is added to the QNode's
+          :class:`~.TransformProgram` and the return is the transformed :class:`~.QNode`.
+          For each execution of the :class:`pennylane.QNode`, it first applies the transform program on the original captured
+          circuit. Then the transformed circuits are executed by a device and finally the post-processing function is
+          applied on the results.
 
-    For QNodes, the dispatched transform populates the ``TransformProgram`` of your QNode. The transform and its
-    processing function are applied in the execution.
+        - For a quantum function (callable) input, the transform builds the tape when the quantum function is
+          executed and then applies itself to the tape. The resulting tape is then converted back
+          to a quantum function (callable). It therefore returns a transformed quantum function (Callable). The limitation
+          is that the underlying transform can only return a sequence containing a single tape, because quantum
+          functions only support a single circuit.
 
-    >>> transformed_qnode = dispatched_transform(qnode_circuit); transformed_qnode
-    <QNode: wires=2, device='<default.qubit device (wires=2) at 0x2a09261c0>', interface='auto', diff_method='best'>
+        - For a :class:`~.QuantumTape`, the underlying quantum transform is directly applied on the
+          :class:`~.QuantumTape`. It returns a sequence of :class:`~.QuantumTape` and a processing
+          function to be applied after execution.
 
-    One subtlety here, this transform would not work for a qfunc because our transform return more than one case. If
-    it was not the case you would be able to dispatch on quantum functions.
+        - For a :class:`~.devices.Device`, the transform is added to the device's transform program
+          and a transformed :class:`pennylane.devices.Device` is returned. The transform is added
+          to the end of the device program and will be last in the overall transform program.
     """
     # 1: Checks for the transform
     if not callable(quantum_transform):
@@ -133,13 +186,14 @@ def transform(
         if not callable(classical_cotransform):
             raise TransformError("The classical co-transform must be a valid Python function.")
 
-    return TransformDispatcher(
+    dispatcher = TransformDispatcher(
         quantum_transform,
         expand_transform=expand_transform,
         classical_cotransform=classical_cotransform,
         is_informative=is_informative,
         final_transform=final_transform,
     )
+    return dispatcher
 
 
 def _transform_signature_check(signature):
diff --git a/pennylane/transforms/core/transform_dispatcher.py b/pennylane/transforms/core/transform_dispatcher.py
index 55383b23c..87a220293 100644
--- a/pennylane/transforms/core/transform_dispatcher.py
+++ b/pennylane/transforms/core/transform_dispatcher.py
@@ -12,8 +12,10 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 """
-This module contains the transform function, the transform dispatcher and the transform container.
+This module contains the transform dispatcher and the transform container.
 """
+import functools
+import os
 import copy
 import warnings
 import types
@@ -22,23 +24,42 @@ import pennylane as qml
 
 
 class TransformError(Exception):
-    """Raised when there is an error with the transform logic"""
+    """Raised when there is an error with the transform logic."""
 
 
 class TransformDispatcher:
-    r"""This object is developer facing and should not be used directly to create transforms. Use
-    :func:`~.pennylane.transforms.core.transform`.
-
-    Convert a transform that has the signature (tape -> Sequence(tape), fn) to a transform dispatcher that can act
-    on tape, qfunc and qnode.
+    r"""Converts a transform that has the signature ``(tape -> Sequence(tape), fn)`` to a transform dispatcher
+    that can act on :class:`pennylane.tape.QuantumTape`, quantum function, :class:`pennylane.QNode`,
+    :class:`pennylane.devices.Device`.
 
     .. warning::
 
-        This class is developer-facing and should not be used directly.
+        This class is developer-facing and should not be used directly. Instead, use
+        :func:`qml.transform <pennylane.transform>` if you would like to make a custom
+        transform.
 
-    .. seealso:: :func:`~.pennylane.transforms.core.transform`
+    .. seealso:: :func:`~.pennylane.transform`
     """
 
+    def __new__(cls, *args, **kwargs):  # pylint: disable=unused-argument
+        if os.environ.get("SPHINX_BUILD") == "1":
+            # If called during a Sphinx documentation build,
+            # simply return the original function rather than
+            # instantiating the object. This allows the signature to
+            # be correctly displayed in the documentation.
+
+            warnings.warn(
+                "Transforms have been disabled, as a Sphinx "
+                "build has been detected via SPHINX_BUILD='1'. If this is not the "
+                "case, please set the environment variable SPHINX_BUILD='0'.",
+                UserWarning,
+            )
+
+            args[0].custom_qnode_transform = lambda x: x
+            return args[0]
+
+        return super().__new__(cls)
+
     # pylint: disable=too-many-arguments
     def __init__(
         self,
@@ -48,15 +69,14 @@ class TransformDispatcher:
         is_informative=False,
         final_transform=False,
     ):  # pylint:disable=redefined-outer-name
-        self.__doc__ = transform.__doc__
         self._transform = transform
         self._expand_transform = expand_transform
         self._classical_cotransform = classical_cotransform
         self._is_informative = is_informative
         # is_informative supersedes final_transform
         self._final_transform = is_informative or final_transform
-
         self._qnode_transform = self.default_qnode_transform
+        functools.update_wrapper(self, transform)
 
     def __call__(self, *targs, **tkwargs):  # pylint: disable=too-many-return-statements
         obj = None
@@ -111,7 +131,9 @@ class TransformDispatcher:
             "Decorating a QNode with @transform_fn(**transform_kwargs) has been "
             "deprecated and will be removed in a future version. Please decorate "
             "with @functools.partial(transform_fn, **transform_kwargs) instead, "
-            "or call the transform directly using qnode = transform_fn(qnode, **transform_kwargs)",
+            "or call the transform directly using qnode = transform_fn(qnode, "
+            "**transform_kwargs). Visit the deprecations page for more details: "
+            "https://docs.pennylane.ai/en/stable/development/deprecations.html",
             UserWarning,
         )
 
@@ -128,36 +150,31 @@ class TransformDispatcher:
         return wrapper
 
     def __repr__(self):
-        return f"<transform: {self.__name__}>"
-
-    @property
-    def __name__(self):
-        """Return the quantum transform name."""
-        return self._transform.__name__
+        return f"<transform: {self._transform.__name__}>"
 
     @property
     def transform(self):
-        """Return the quantum transform."""
+        """The quantum transform."""
         return self._transform
 
     @property
     def expand_transform(self):
-        """Return the expand transform."""
+        """The expand transform."""
         return self._expand_transform
 
     @property
     def classical_cotransform(self):
-        """Return the classical co-transform."""
+        """The classical co-transform."""
         return self._classical_cotransform
 
     @property
     def is_informative(self):
-        """Return True is the transform is informative."""
+        """``True`` if the transform is informative."""
         return self._is_informative
 
     @property
     def final_transform(self):
-        """Return True if the transformed tapes must be executed."""
+        """``True`` if the transformed tapes must be executed."""
         return self._final_transform
 
     def custom_qnode_transform(self, fn):
@@ -311,14 +328,16 @@ class TransformDispatcher:
 
 
 class TransformContainer:
-    """Class to store a quantum transform with its args, kwargs and classical co-transforms.  Use
-    :func:`~.pennylane.transforms.core.transform`.
+    """Class to store a quantum transform with its ``args``, ``kwargs`` and classical co-transforms.  Use
+    :func:`~.pennylane.transform`.
 
     .. warning::
 
-        This class is developer-facing and should not be used directly.
+        This class is developer-facing and should not be used directly. Instead, use
+        :func:`qml.transform <pennylane.transform>` if you would like to make a custom
+        transform.
 
-    .. seealso:: :func:`~.pennylane.transforms.core.transform`
+    .. seealso:: :func:`~.pennylane.transform`
     """
 
     def __init__(
@@ -351,30 +370,30 @@ class TransformContainer:
 
     @property
     def transform(self):
-        """Return the stored quantum transform."""
+        """The stored quantum transform."""
         return self._transform
 
     @property
     def args(self):
-        """Return the stored quantum transform's args."""
+        """The stored quantum transform's ``args``."""
         return self._args
 
     @property
     def kwargs(self):
-        """Return the stored quantum transform's arkwgs."""
+        """The stored quantum transform's ``kwargs``."""
         return self._kwargs
 
     @property
     def classical_cotransform(self):
-        """Return the stored quantum transform's classical co-transform."""
+        """The stored quantum transform's classical co-transform."""
         return self._classical_cotransform
 
     @property
     def is_informative(self):
-        """Return True is the transform is informative."""
+        """``True`` if the transform is informative."""
         return self._is_informative
 
     @property
     def final_transform(self):
-        """Return True if the transform needs to be executed"""
+        """``True`` if the transform needs to be executed"""
         return self._final_transform
diff --git a/pennylane/transforms/core/transform_program.py b/pennylane/transforms/core/transform_program.py
index d6ee51fc9..c21037d28 100644
--- a/pennylane/transforms/core/transform_program.py
+++ b/pennylane/transforms/core/transform_program.py
@@ -12,7 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 """
-This module contains the transform program class.
+This module contains the ``TransformProgram`` class.
 """
 from functools import partial
 from typing import Callable, List, Tuple, Optional, Sequence
@@ -101,14 +101,21 @@ def null_postprocessing(results: ResultBatch) -> ResultBatch:
 
 
 class TransformProgram:
-    """Class that contains a transform program and the methods to interact with it. The order of execution is the order
-    in the list containing the containers.
+    """Class that contains a transform program and the methods to interact with it.
+
+    The order of execution is the order in the list containing the containers.
+
+    The main case where one would have to interact directly with a transform program is when developing a
+    :class:`Device <pennylane.devices.Device>`. In this case, the pre-processing method of a device
+    returns a transform program. You should directly refer to the device API documentation for more details.
 
     .. warning::
 
-        This class is developer-facing and should not be used directly.
+        This class is developer-facing and should not be used directly. Instead, use
+        :func:`qml.transform <pennylane.transform>` if you would like to make a custom
+        transform.
 
-    .. seealso:: :func:`~.pennylane.transforms.core.transform`
+    .. seealso:: :func:`~.pennylane.transform`
 
     """
 
@@ -178,7 +185,7 @@ class TransformProgram:
         """Add a transform (dispatcher) to the end of the program.
 
         Note that this should be a function decorated with/called by
-        `qml.transforms.transform`, and not a `TransformContainer`.
+        ``qml.transforms.transform``, and not a ``TransformContainer``.
 
         Args:
             transform (TransformDispatcher): The transform to add to the transform program.
@@ -267,7 +274,7 @@ class TransformProgram:
 
     @property
     def is_informative(self) -> bool:
-        """Check if the transform program is informative or not.
+        """``True`` if the transform program is informative.
 
         Returns:
             bool: Boolean
@@ -276,7 +283,7 @@ class TransformProgram:
 
     @property
     def has_final_transform(self) -> bool:
-        """Check if the transform program has a terminal transform or not."""
+        """``True`` if the transform program has a terminal transform."""
         return self[-1].final_transform if self else False
 
     def has_classical_cotransform(self) -> bool:
diff --git a/pennylane/transforms/defer_measurements.py b/pennylane/transforms/defer_measurements.py
index c39bb0819..3626a83d7 100644
--- a/pennylane/transforms/defer_measurements.py
+++ b/pennylane/transforms/defer_measurements.py
@@ -18,7 +18,7 @@ from pennylane.measurements import MidMeasureMP, ProbabilityMP, SampleMP, Counts
 from pennylane.ops.op_math import ctrl
 
 from pennylane.tape import QuantumTape
-from pennylane.transforms.core import transform
+from pennylane.transforms import transform
 
 from pennylane.wires import Wires
 from pennylane.queuing import QueuingManager
@@ -140,14 +140,10 @@ def defer_measurements(tape: QuantumTape, **kwargs) -> (Sequence[QuantumTape], C
         or an observable are explicitly specified.
 
     Args:
-        tape (.QuantumTape): a quantum tape
+        tape (QNode or QuantumTape or Callable): a quantum circuit.
 
     Returns:
-        pennylane.QNode or qfunc or tuple[List[.QuantumTape], function]: If a QNode is passed,
-        it returns a QNode with the transform added to its transform program.
-        If a tape is passed, returns a tuple containing a list of
-        quantum tapes to be evaluated, and a function to be applied to these
-        tape executions.
+        qnode (QNode) or quantum function (Callable) or tuple[List[QuantumTape], function]: The transformed circuit as described in :func:`qml.transform <pennylane.transform>`.
 
     **Example**
 
diff --git a/pennylane/transforms/hamiltonian_expand.py b/pennylane/transforms/hamiltonian_expand.py
index 139238c19..487d92ba8 100644
--- a/pennylane/transforms/hamiltonian_expand.py
+++ b/pennylane/transforms/hamiltonian_expand.py
@@ -21,7 +21,7 @@ import pennylane as qml
 from pennylane.measurements import ExpectationMP, MeasurementProcess
 from pennylane.ops import SProd, Sum
 from pennylane.tape import QuantumScript, QuantumTape
-from pennylane.transforms.core import transform
+from pennylane.transforms import transform
 
 
 @transform
@@ -31,15 +31,13 @@ def hamiltonian_expand(tape: QuantumTape, group: bool = True) -> (Sequence[Quant
     and provides a function to recombine the results.
 
     Args:
-        tape (.QuantumTape): the tape used when calculating the expectation value
-            of the Hamiltonian
+        tape (QNode or QuantumTape or Callable): the quantum circuit used when calculating the
+            expectation value of the Hamiltonian
         group (bool): Whether to compute disjoint groups of commuting Pauli observables, leading to fewer tapes.
             If grouping information can be found in the Hamiltonian, it will be used even if group=False.
 
     Returns:
-        tuple[Sequence[.QuantumTape], Callable]: Returns a tuple containing a list of
-        quantum tapes to be evaluated, and a function to be applied to these
-        tape executions to compute the expectation value.
+        qnode (QNode) or tuple[List[QuantumTape], function]: The transformed circuit as described in :func:`qml.transform <pennylane.transform>`.
 
     **Example**
 
diff --git a/pennylane/transforms/insert_ops.py b/pennylane/transforms/insert_ops.py
index 0e8ea6a03..1686e1c98 100644
--- a/pennylane/transforms/insert_ops.py
+++ b/pennylane/transforms/insert_ops.py
@@ -20,7 +20,7 @@ from typing import Type, Union, Callable, Sequence
 import pennylane as qml
 from pennylane.operation import Operation
 from pennylane.tape import QuantumTape
-from pennylane.transforms.core import transform
+from pennylane.transforms import transform
 from pennylane.ops.op_math import Adjoint
 
 # pylint: disable=too-many-branches
@@ -69,7 +69,7 @@ def insert(
     for more information).
 
     Args:
-        circuit (QuantumTape): the input circuit to be transformed.
+        tape (QNode or QuantumTape or Callable or pennylane.devices.Device): the input circuit to be transformed.
         op (callable or Type[Operation]): the single-qubit operation, or sequence of operations
             acting on a single qubit, to be inserted into the circuit
         op_args (tuple or float): the arguments fed to the operation, either as a tuple or a single
@@ -83,8 +83,10 @@ def insert(
             Default is ``False`` and the operation is inserted after.
 
     Returns:
-        callable or QuantumTape or pennylane.Device: the updated version of the input circuit or an updated
-        device which will transform circuits before execution
+        qnode (QNode) or quantum function (Callable) or tuple[List[.QuantumTape], function] or device (pennylane.devices.Device):
+
+        The transformed circuit as described in :func:`qml.transform <pennylane.transform>`.
+
 
     Raises:
         QuantumFunctionError: if some observables in the tape are not qubit-wise commuting
@@ -100,8 +102,8 @@ def insert(
 
         dev = qml.device("default.mixed", wires=2)
 
+        @partial(qml.transforms.insert, qml.AmplitudeDamping, 0.2, position="end")
         @qml.qnode(dev)
-        @qml.transforms.insert(qml.AmplitudeDamping, 0.2, position="end")
         def f(w, x, y, z):
             qml.RX(w, wires=0)
             qml.RY(x, wires=1)
@@ -173,7 +175,7 @@ def insert(
         We can add the :class:`~.AmplitudeDamping` channel to the end of the circuit using:
 
         >>> from pennylane.transforms import insert
-        >>> noisy_tape = insert(qml.AmplitudeDamping, 0.05, position="end")(tape)
+        >>> noisy_tape = insert(tape, qml.AmplitudeDamping, 0.05, position="end")
         >>> print(qml.drawer.tape_text(noisy_tape, decimals=2))
         0: ──RX(0.90)─╭●──RY(0.50)──AmplitudeDamping(0.05)─┤ ╭<Z@Z>
         1: ──RY(0.40)─╰X──RX(0.60)──AmplitudeDamping(0.05)─┤ ╰<Z@Z>
@@ -203,7 +205,7 @@ def insert(
 
         However, noise can be easily added to the device:
 
-        >>> dev_noisy = qml.transforms.insert(qml.AmplitudeDamping, 0.2)(dev)
+        >>> dev_noisy = qml.transforms.insert(dev, qml.AmplitudeDamping, 0.2)
         >>> qnode_noisy = qml.QNode(f, dev_noisy)
         >>> qnode_noisy(0.9, 0.4, 0.5, 0.6)
         tensor(0.72945434, requires_grad=True)
diff --git a/pennylane/transforms/metric_tensor.py b/pennylane/transforms/metric_tensor.py
index a65cae2af..500123190 100644
--- a/pennylane/transforms/metric_tensor.py
+++ b/pennylane/transforms/metric_tensor.py
@@ -24,7 +24,7 @@ import numpy as np
 import pennylane as qml
 from pennylane.circuit_graph import LayerData
 from pennylane.queuing import WrappedObj
-from pennylane.transforms.core import transform
+from pennylane.transforms import transform
 
 
 def _contract_metric_tensor_with_cjac(mt, cjac, tape):  # pylint: disable=unused-argument
@@ -118,7 +118,7 @@ def metric_tensor(  # pylint:disable=too-many-arguments
         This is the case for unitary single-parameter operations.
 
     Args:
-        tape (QuantumTape): quantum tape to find the metric tensor of
+        tape (QNode or QuantumTape): quantum circuit to find the metric tensor of
         argnum (int or Sequence[int] or None): Trainable tape-parameter indices with respect to which
             the metric tensor is computed. If ``argnum=None``, the metric tensor with respect to all
             trainable parameters is returned. Excluding tape-parameter indices from this list reduces
@@ -159,16 +159,10 @@ def metric_tensor(  # pylint:disable=too-many-arguments
               The output shape is a single two-dimensional tensor.
 
     Returns:
-        function or tuple[list[QuantumTape], function]:
+        qnode (QNode) or tuple[List[QuantumTape], function]:
 
-        - If the input is a QNode, an object representing the metric tensor (function) of the
-          QNode that takes the same arguments as the QNode and can be executed to obtain the
-          metric tensor (matrix).
-
-        - If the input is a tape, a tuple containing a
-          list of generated tapes, together with a post-processing
-          function to be applied to the results of the evaluated tapes
-          in order to obtain the metric tensor.
+        The transformed circuit as described in :func:`qml.transform <pennylane.transform>`. Executing this circuit
+        will provide the metric tensor in the form of a tensor.
 
     The block-diagonal part of the metric tensor always is computed using the
     covariance-based approach. If no approximation is selected,
diff --git a/pennylane/transforms/mitigate.py b/pennylane/transforms/mitigate.py
index 4964b5d62..d88f02e4f 100644
--- a/pennylane/transforms/mitigate.py
+++ b/pennylane/transforms/mitigate.py
@@ -20,7 +20,7 @@ from pennylane import apply, adjoint
 from pennylane.math import mean, shape, round
 from pennylane.queuing import AnnotatedQueue
 from pennylane.tape import QuantumTape, QuantumScript
-from pennylane.transforms.core import transform
+from pennylane.transforms import transform
 
 import pennylane as qml
 
@@ -37,18 +37,11 @@ def fold_global(tape: QuantumTape, scale_factor) -> (Sequence[QuantumTape], Call
     The purpose of folding is to artificially increase the noise for zero noise extrapolation, see :func:`~.pennylane.transforms.mitigate_with_zne`.
 
     Args:
-        tape (~.QuantumTape): the circuit to be folded
+        tape (QNode or QuantumTape): the quantum circuit to be folded
         scale_factor (float): Scale factor :math:`\lambda` determining :math:`n` and :math:`s`
 
     Returns:
-        function or tuple[list[QuantumTape], function]:
-
-        - If the input is a QNode, an object representing the folded QNode that can be executed
-          with the same arguments as the QNode to obtain the result of the folded circuit.
-
-        - If the input is a tape, a tuple containing a (single-entry) list of generated
-          circuits, together with a post-processing function that extracts the single tape result
-          from the evaluated tape list in order to obtain the result of the folded circuit.
+        qnode (QNode) or tuple[List[QuantumTape], function]: The folded circuit as described in :func:`qml.transform <pennylane.transform>`.
 
     .. seealso:: :func:`~.pennylane.transforms.mitigate_with_zne`; This function is analogous to the implementation in ``mitiq``  `mitiq.zne.scaling.fold_global <https://mitiq.readthedocs.io/en/v.0.1a2/apidoc.html?highlight=global_folding#mitiq.zne.scaling.fold_global>`_.
 
@@ -354,7 +347,7 @@ def mitigate_with_zne(
     see the example and usage details for further information.
 
     Args:
-        tape (~.QuantumTape): the circuit to be error-mitigated
+        tape (QNode or QuantumTape): the quantum circuit to be error-mitigated
         scale_factors (Sequence[float]): the range of noise scale factors used
         folding (callable): a function that returns a folded circuit for a specified scale factor
         extrapolate (callable): a function that returns an extrapolated result when provided a
@@ -365,7 +358,11 @@ def mitigate_with_zne(
             folding function is stochastic.
 
     Returns:
-        float: the result of evaluating the circuit when mitigated using ZNE
+        qnode (QNode) or tuple[List[.QuantumTape], function]:
+
+        The transformed circuit as described in :func:`qml.transform <pennylane.transform>`. Executing this circuit
+        will provide the mitigated results in the form of a tensor of a tensor, a tuple, or a nested tuple depending
+        upon the nesting structure of measurements in the original circuit.
 
     **Example:**
 
@@ -388,6 +385,7 @@ def mitigate_with_zne(
 
     .. code-block:: python3
 
+        from functools import partial
         from pennylane import numpy as np
         from pennylane import qnode
 
@@ -400,7 +398,7 @@ def mitigate_with_zne(
         np.random.seed(0)
         w1, w2 = [np.random.random(s) for s in shapes]
 
-        @qml.transforms.mitigate_with_zne([1., 2., 3.], fold_global, poly_extrapolate, extrapolate_kwargs={'order': 2})
+        @partial(qml.transforms.mitigate_with_zne, [1., 2., 3.], fold_global, poly_extrapolate, extrapolate_kwargs={'order': 2})
         @qnode(dev)
         def circuit(w1, w2):
             qml.SimplifiedTwoDesign(w1, w2, wires=range(2))
diff --git a/pennylane/transforms/optimization/cancel_inverses.py b/pennylane/transforms/optimization/cancel_inverses.py
index a81556691..44b5c4985 100644
--- a/pennylane/transforms/optimization/cancel_inverses.py
+++ b/pennylane/transforms/optimization/cancel_inverses.py
@@ -18,7 +18,7 @@ from typing import Sequence, Callable
 from pennylane.ops.op_math import Adjoint
 from pennylane.wires import Wires
 from pennylane.tape import QuantumTape
-from pennylane.transforms.core import transform
+from pennylane.transforms import transform
 
 from pennylane.ops.qubit.attributes import (
     self_inverses,
@@ -69,22 +69,23 @@ def cancel_inverses(tape: QuantumTape) -> (Sequence[QuantumTape], Callable):
     (self-)inverses or adjoint.
 
     Args:
-        tape (~.QuantumTape): A quantum tape
+        tape (QNode or QuantumTape or Callable): A quantum circuit.
 
     Returns:
-        pennylane.QNode or qfunc or tuple[List[.QuantumTape], function]: If a QNode is passed,
-        it returns a QNode with the transform added to its transform program.
-        If a tape is passed, returns a tuple containing a list of
-        quantum tapes to be evaluated, and a function to be applied to these
-        tape executions.
+        qnode (QNode) or quantum function (Callable) or tuple[List[QuantumTape], function]: The transformed circuit as described in :func:`qml.transform <pennylane.transform>`.
+
 
     **Example**
 
-    Consider the following quantum function:
+    You can apply the cancel inverses transform directly on :class:`~.QNode`.
+
+    >>> dev = qml.device('default.qubit', wires=3)
 
     .. code-block:: python
 
-        def qfunc(x, y, z):
+        @cancel_inverses
+        @qml.qnode(device=dev)
+        def circuit(x, y, z):
             qml.Hadamard(wires=0)
             qml.Hadamard(wires=1)
             qml.Hadamard(wires=0)
@@ -97,26 +98,48 @@ def cancel_inverses(tape: QuantumTape) -> (Sequence[QuantumTape], Callable):
             qml.PauliX(wires=1)
             return qml.expval(qml.PauliZ(0))
 
-    The circuit before optimization:
-
-    >>> dev = qml.device('default.qubit', wires=3)
-    >>> qnode = qml.QNode(qfunc, dev)
-    >>> print(qml.draw(qnode)(1, 2, 3))
-    0: ──H─────────H─────────RZ(3.00)─╭●────┤  <Z>
-    1: ──H─────────RY(2.00)──X────────│───X─┤
-    2: ──RX(1.00)──RX(2.00)───────────╰X────┤
-
-    We can see that there are two adjacent Hadamards on the first qubit that
-    should cancel each other out. Similarly, there are two Pauli-X gates on the
-    second qubit that should cancel. We can obtain a simplified circuit by running
-    the ``cancel_inverses`` transform:
-
-    >>> optimized_qfunc = cancel_inverses(qfunc)
-    >>> optimized_qnode = qml.QNode(optimized_qfunc, dev)
-    >>> print(qml.draw(optimized_qnode)(1, 2, 3))
-    0: ──RZ(3.00)───────────╭●─┤  <Z>
-    1: ──H─────────RY(2.00)─│──┤
-    2: ──RX(1.00)──RX(2.00)─╰X─┤
+    >>> circuit(0.1, 0.2, 0.3)
+    0.999999999999999
+
+    .. details::
+        :title: Usage Details
+
+        You can also apply it on quantum functions:
+
+        .. code-block:: python
+
+            def qfunc(x, y, z):
+                qml.Hadamard(wires=0)
+                qml.Hadamard(wires=1)
+                qml.Hadamard(wires=0)
+                qml.RX(x, wires=2)
+                qml.RY(y, wires=1)
+                qml.PauliX(wires=1)
+                qml.RZ(z, wires=0)
+                qml.RX(y, wires=2)
+                qml.CNOT(wires=[0, 2])
+                qml.PauliX(wires=1)
+                return qml.expval(qml.PauliZ(0))
+
+        The circuit before optimization:
+
+        >>> qnode = qml.QNode(qfunc, dev)
+        >>> print(qml.draw(qnode)(1, 2, 3))
+        0: ──H─────────H─────────RZ(3.00)─╭●────┤  <Z>
+        1: ──H─────────RY(2.00)──X────────│───X─┤
+        2: ──RX(1.00)──RX(2.00)───────────╰X────┤
+
+        We can see that there are two adjacent Hadamards on the first qubit that
+        should cancel each other out. Similarly, there are two Pauli-X gates on the
+        second qubit that should cancel. We can obtain a simplified circuit by running
+        the ``cancel_inverses`` transform:
+
+        >>> optimized_qfunc = cancel_inverses(qfunc)
+        >>> optimized_qnode = qml.QNode(optimized_qfunc, dev)
+        >>> print(qml.draw(optimized_qnode)(1, 2, 3))
+        0: ──RZ(3.00)───────────╭●─┤  <Z>
+        1: ──H─────────RY(2.00)─│──┤
+        2: ──RX(1.00)──RX(2.00)─╰X─┤
 
     """
     # Make a working copy of the list to traverse
diff --git a/pennylane/transforms/optimization/commute_controlled.py b/pennylane/transforms/optimization/commute_controlled.py
index 4260495b3..3b71f76a6 100644
--- a/pennylane/transforms/optimization/commute_controlled.py
+++ b/pennylane/transforms/optimization/commute_controlled.py
@@ -15,7 +15,7 @@
 from typing import Sequence, Callable
 
 from pennylane.tape import QuantumTape
-from pennylane.transforms.core import transform
+from pennylane.transforms import transform
 from pennylane.wires import Wires
 
 from .optimization_utils import find_next_gate
@@ -157,26 +157,27 @@ def commute_controlled(tape: QuantumTape, direction="right") -> (Sequence[Quantu
     """Quantum transform to move commuting gates past control and target qubits of controlled operations.
 
     Args:
-        tape (QuantumTape): A quantum tape.
+        tape (QNode or QuantumTape or Callable): A quantum circuit.
         direction (str): The direction in which to move single-qubit gates.
             Options are "right" (default), or "left". Single-qubit gates will
             be pushed through controlled operations as far as possible in the
             specified direction.
 
     Returns:
-        pennylane.QNode or qfunc or tuple[List[.QuantumTape], function]: If a QNode is passed,
-        it returns a QNode with the transform added to its transform program. If a qfunc is passed,
-        it returns a transformed quantum function. If a tape is passed, returns a tuple containing a list of
-        quantum tapes to be evaluated, and a function to be applied to these
-        tape executions.
+        qnode (QNode) or quantum function (Callable) or tuple[List[QuantumTape], function]: The transformed circuit as described in :func:`qml.transform <pennylane.transform>`.
+
 
     **Example**
 
-    Consider the following quantum function.
+    >>> dev = qml.device('default.qubit', wires=3)
+
+    You can apply the transform directly on :class:`QNode`:
 
     .. code-block:: python
 
-        def qfunc(theta):
+        @partial(commute_controlled, direction="right")
+        @qml.qnode(device=dev)
+        def circuit(theta):
             qml.CZ(wires=[0, 2])
             qml.PauliX(wires=2)
             qml.S(wires=0)
@@ -193,26 +194,52 @@ def commute_controlled(tape: QuantumTape, direction="right") -> (Sequence[Quantu
 
             return qml.expval(qml.PauliZ(0))
 
-    >>> dev = qml.device('default.qubit', wires=3)
-    >>> qnode = qml.QNode(qfunc, dev)
-    >>> print(qml.draw(qnode)(0.5))
-    0: ─╭●──S─╭●────╭●─────────Rϕ(0.25)─╭●──T────────┤  <Z>
-    1: ─│─────╰X──Y─╰RY(0.50)───────────├●──RZ(0.25)─┤
-    2: ─╰Z──X───────────────────────────╰X───────────┤
-
-    Diagonal gates on either side of control qubits do not affect the outcome
-    of controlled gates; thus we can push all the single-qubit gates on the
-    first qubit together on the right (and fuse them if desired). Similarly, X
-    gates commute with the target of ``CNOT`` and ``Toffoli`` (and ``PauliY``
-    with ``CRY``). We can use the transform to push single-qubit gates as
-    far as possible through the controlled operations:
-
-    >>> optimized_qfunc = commute_controlled(direction="right")(qfunc)
-    >>> optimized_qnode = qml.QNode(optimized_qfunc, dev)
-    >>> print(qml.draw(optimized_qnode)(0.5))
-    0: ─╭●─╭●─╭●───────────╭●──S─────────Rϕ(0.25)──T─┤  <Z>
-    1: ─│──╰X─╰RY(0.50)──Y─├●──RZ(0.25)──────────────┤
-    2: ─╰Z─────────────────╰X──X─────────────────────┤
+    >>> circuit(0.5)
+    0.9999999999999999
+
+    .. details::
+        :title: Usage Details
+
+        You can also apply it on quantum function.
+
+        .. code-block:: python
+
+            def qfunc(theta):
+                qml.CZ(wires=[0, 2])
+                qml.PauliX(wires=2)
+                qml.S(wires=0)
+
+                qml.CNOT(wires=[0, 1])
+
+                qml.PauliY(wires=1)
+                qml.CRY(theta, wires=[0, 1])
+                qml.PhaseShift(theta/2, wires=0)
+
+                qml.Toffoli(wires=[0, 1, 2])
+                qml.T(wires=0)
+                qml.RZ(theta/2, wires=1)
+
+                return qml.expval(qml.PauliZ(0))
+
+        >>> qnode = qml.QNode(qfunc, dev)
+        >>> print(qml.draw(qnode)(0.5))
+        0: ─╭●──S─╭●────╭●─────────Rϕ(0.25)─╭●──T────────┤  <Z>
+        1: ─│─────╰X──Y─╰RY(0.50)───────────├●──RZ(0.25)─┤
+        2: ─╰Z──X───────────────────────────╰X───────────┤
+
+        Diagonal gates on either side of control qubits do not affect the outcome
+        of controlled gates; thus we can push all the single-qubit gates on the
+        first qubit together on the right (and fuse them if desired). Similarly, X
+        gates commute with the target of ``CNOT`` and ``Toffoli`` (and ``PauliY``
+        with ``CRY``). We can use the transform to push single-qubit gates as
+        far as possible through the controlled operations:
+
+        >>> optimized_qfunc = commute_controlled(qfunc, direction="right")
+        >>> optimized_qnode = qml.QNode(optimized_qfunc, dev)
+        >>> print(qml.draw(optimized_qnode)(0.5))
+        0: ─╭●─╭●─╭●───────────╭●──S─────────Rϕ(0.25)──T─┤  <Z>
+        1: ─│──╰X─╰RY(0.50)──Y─├●──RZ(0.25)──────────────┤
+        2: ─╰Z─────────────────╰X──X─────────────────────┤
 
     """
     if direction not in ("left", "right"):
diff --git a/pennylane/transforms/optimization/merge_amplitude_embedding.py b/pennylane/transforms/optimization/merge_amplitude_embedding.py
index 40216c0ee..44d688cc6 100644
--- a/pennylane/transforms/optimization/merge_amplitude_embedding.py
+++ b/pennylane/transforms/optimization/merge_amplitude_embedding.py
@@ -14,7 +14,7 @@
 """Transform for merging AmplitudeEmbedding gates in a quantum circuit."""
 from typing import Sequence, Callable
 
-from pennylane.transforms.core import transform
+from pennylane.transforms import transform
 from pennylane.tape import QuantumTape
 from pennylane import AmplitudeEmbedding
 from pennylane._device import DeviceError
@@ -26,39 +26,57 @@ def merge_amplitude_embedding(tape: QuantumTape) -> (Sequence[QuantumTape], Call
     r"""Quantum function transform to combine amplitude embedding templates that act on different qubits.
 
     Args:
-        tape (QuantumTape): A quantum tape.
+        tape (QNode or QuantumTape or Callable): A quantum circuit.
 
     Returns:
-        pennylane.QNode or qfunc or tuple[List[.QuantumTape], function]: If a QNode is passed,
-        it returns a QNode with the transform added to its transform program.
-        If a tape is passed, returns a tuple containing a list of
-        quantum tapes to be evaluated, and a function to be applied to these
-        tape executions.
+        qnode (QNode) or quantum function (Callable) or tuple[List[.QuantumTape], function]: The transformed circuit as described in :func:`qml.transform <pennylane.transform>`.
+
 
     **Example**
 
-    Consider the following quantum function.
+    >>> dev = qml.device('default.qubit', wires=4)
+
+    You can apply the transform directly on :class:`QNode`:
 
     .. code-block:: python
 
-        def qfunc():
+        @qml.transforms.merge_amplitude_embedding
+        @qml.qnode(device=dev)
+        def circuit():
             qml.CNOT(wires = [0,1])
             qml.AmplitudeEmbedding([0,1], wires = 2)
             qml.AmplitudeEmbedding([0,1], wires = 3)
             return qml.state()
 
-    The circuit before compilation will not work because of using two amplitude embedding.
+    >>> circuit()
+    [1.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j]
 
-    Using the transformation we can join the different amplitude embedding into a single one:
+    .. details::
+        :title: Usage Details
 
-    >>> dev = qml.device('default.qubit', wires=4)
-    >>> optimized_qfunc = qml.transforms.merge_amplitude_embedding(qfunc)
-    >>> optimized_qnode = qml.QNode(optimized_qfunc, dev)
-    >>> print(qml.draw(optimized_qnode)())
-    0: ─╭●───┤  State
-    1: ─╰X───┤  State
-    2: ─╭|Ψ⟩─┤  State
-    3: ─╰|Ψ⟩─┤  State
+        You can also apply it on quantum function.
+
+        .. code-block:: python
+
+            def qfunc():
+                qml.CNOT(wires = [0,1])
+                qml.AmplitudeEmbedding([0,1], wires = 2)
+                qml.AmplitudeEmbedding([0,1], wires = 3)
+                return qml.state()
+
+        The circuit before compilation will not work because of using two amplitude embedding.
+
+        Using the transformation we can join the different amplitude embedding into a single one:
+
+        >>> optimized_qfunc = qml.transforms.merge_amplitude_embedding(qfunc)
+        >>> optimized_qnode = qml.QNode(optimized_qfunc, dev)
+        >>> print(qml.draw(optimized_qnode)())
+        0: ─╭●──────────────────────┤  State
+        1: ─╰X──────────────────────┤  State
+        2: ─╭AmplitudeEmbedding(M0)─┤  State
+        3: ─╰AmplitudeEmbedding(M0)─┤  State
+        M0 =
+        [0.+0.j 0.+0.j 0.+0.j 1.+0.j]
 
     """
     # Make a working copy of the list to traverse
diff --git a/pennylane/transforms/optimization/merge_rotations.py b/pennylane/transforms/optimization/merge_rotations.py
index ee183a5a5..91cb67efa 100644
--- a/pennylane/transforms/optimization/merge_rotations.py
+++ b/pennylane/transforms/optimization/merge_rotations.py
@@ -16,7 +16,7 @@
 from typing import Sequence, Callable
 
 from pennylane.tape import QuantumTape
-from pennylane.transforms.core import transform
+from pennylane.transforms import transform
 from pennylane.math import allclose, stack, cast_like, zeros, is_abstract
 from pennylane.queuing import QueuingManager
 
@@ -35,7 +35,7 @@ def merge_rotations(
     neither gate will be applied.
 
     Args:
-        tape (QuantumTape): A quantum tape.
+        tape (QNode or QuantumTape or Callable): A quantum circuit.
         atol (float): After fusion of gates, if the fused angle :math:`\theta` is such that
             :math:`|\theta|\leq \text{atol}`, no rotation gate will be applied.
         include_gates (None or list[str]): A list of specific operations to merge. If
@@ -44,19 +44,19 @@ def merge_rotations(
             only the operations whose names match those in the list will undergo merging.
 
     Returns:
-        pennylane.QNode or qfunc or tuple[List[.QuantumTape], function]: If a QNode is passed,
-        it returns a QNode with the transform added to its transform program.
-        If a tape is passed, returns a tuple containing a list of
-        quantum tapes to be evaluated, and a function to be applied to these
-        tape executions.
+        qnode (QNode) or quantum function (Callable) or tuple[List[QuantumTape], function]: The transformed circuit as described in :func:`qml.transform <pennylane.transform>`.
 
     **Example**
 
-    Consider the following quantum function.
+    >>> dev = qml.device('default.qubit', wires=3)
+
+    You can apply the transform directly on :class:`QNode`
 
     .. code-block:: python
 
-        def qfunc(x, y, z):
+        @merge_rotations
+        @qml.qnode(device=dev)
+        def circuit(x, y, z):
             qml.RX(x, wires=0)
             qml.RX(y, wires=0)
             qml.CNOT(wires=[1, 2])
@@ -66,35 +66,54 @@ def merge_rotations(
             qml.RY(-y, wires=1)
             return qml.expval(qml.PauliZ(0))
 
-    The circuit before optimization:
-
-    >>> dev = qml.device('default.qubit', wires=3)
-    >>> qnode = qml.QNode(qfunc, dev)
-    >>> print(qml.draw(qnode)(1, 2, 3))
-    0: ──RX(1.00)──RX(2.00)─╭RZ(3.00)────────────┤  <Z>
-    1: ─╭●─────────RY(2.00)─│──────────RY(-2.00)─┤
-    2: ─╰X─────────H────────╰●───────────────────┤
-
-    By inspection, we can combine the two ``RX`` rotations on the first qubit.
-    On the second qubit, we have a cumulative angle of 0, and the gates will cancel.
-
-    >>> optimized_qfunc = merge_rotations(qfunc)
-    >>> optimized_qnode = qml.QNode(optimized_qfunc, dev)
-    >>> print(qml.draw(optimized_qnode)(1, 2, 3))
-    0: ──RX(3.00)────╭RZ(3.00)─┤  <Z>
-    1: ─╭●───────────│─────────┤
-    2: ─╰X─────────H─╰●────────┤
-
-    It is also possible to explicitly specify which rotations ``merge_rotations`` should
-    be merged using the ``include_gates`` argument. For example, if in the above
-    circuit we wanted only to merge the "RX" gates, we could do so as follows:
-
-    >>> optimized_qfunc = merge_rotations(qfunc, include_gates=["RX"])
-    >>> optimized_qnode = qml.QNode(optimized_qfunc, dev)
-    >>> print(qml.draw(optimized_qnode)(1, 2, 3))
-    0: ──RX(3.00)───────────╭RZ(3.00)────────────┤  <Z>
-    1: ─╭●─────────RY(2.00)─│──────────RY(-2.00)─┤
-    2: ─╰X─────────H────────╰●───────────────────┤
+    >>> circuit(0.1, 0.2, 0.3)
+    0.9553364891256055
+
+    .. details::
+        :title: Usage Details
+
+        You can also apply it on quantum function.
+
+        .. code-block:: python
+
+            def qfunc(x, y, z):
+                qml.RX(x, wires=0)
+                qml.RX(y, wires=0)
+                qml.CNOT(wires=[1, 2])
+                qml.RY(y, wires=1)
+                qml.Hadamard(wires=2)
+                qml.CRZ(z, wires=[2, 0])
+                qml.RY(-y, wires=1)
+                return qml.expval(qml.PauliZ(0))
+
+        The circuit before optimization:
+
+        >>> qnode = qml.QNode(qfunc, dev)
+        >>> print(qml.draw(qnode)(1, 2, 3))
+        0: ──RX(1.00)──RX(2.00)─╭RZ(3.00)────────────┤  <Z>
+        1: ─╭●─────────RY(2.00)─│──────────RY(-2.00)─┤
+        2: ─╰X─────────H────────╰●───────────────────┤
+
+        By inspection, we can combine the two ``RX`` rotations on the first qubit.
+        On the second qubit, we have a cumulative angle of 0, and the gates will cancel.
+
+        >>> optimized_qfunc = merge_rotations()(qfunc)
+        >>> optimized_qnode = qml.QNode(optimized_qfunc, dev)
+        >>> print(qml.draw(optimized_qnode)(1, 2, 3))
+        0: ──RX(3.00)────╭RZ(3.00)─┤  <Z>
+        1: ─╭●───────────│─────────┤
+        2: ─╰X─────────H─╰●────────┤
+
+        It is also possible to explicitly specify which rotations ``merge_rotations`` should
+        be merged using the ``include_gates`` argument. For example, if in the above
+        circuit we wanted only to merge the "RX" gates, we could do so as follows:
+
+        >>> optimized_qfunc = merge_rotations(include_gates=["RX"])(qfunc)
+        >>> optimized_qnode = qml.QNode(optimized_qfunc, dev)
+        >>> print(qml.draw(optimized_qnode)(1, 2, 3))
+        0: ──RX(3.00)───────────╭RZ(3.00)────────────┤  <Z>
+        1: ─╭●─────────RY(2.00)─│──────────RY(-2.00)─┤
+        2: ─╰X─────────H────────╰●───────────────────┤
 
     """
     # Expand away adjoint ops
diff --git a/pennylane/transforms/optimization/pattern_matching.py b/pennylane/transforms/optimization/pattern_matching.py
index 77f34d0a6..113e9efe1 100644
--- a/pennylane/transforms/optimization/pattern_matching.py
+++ b/pennylane/transforms/optimization/pattern_matching.py
@@ -22,7 +22,7 @@ from typing import Sequence, Callable
 import numpy as np
 
 import pennylane as qml
-from pennylane.transforms.core import transform
+from pennylane.transforms import transform
 from pennylane import adjoint
 from pennylane.ops.qubit.attributes import symmetric_over_all_wires
 from pennylane.tape import QuantumTape, QuantumScript
@@ -38,16 +38,12 @@ def pattern_matching_optimization(
     r"""Quantum function transform to optimize a circuit given a list of patterns (templates).
 
     Args:
-        tape (QuantumTape): A quantum tape to be optimized.
+        tape (QNode or QuantumTape or Callable): A quantum circuit to be optimized.
         pattern_tapes(list(.QuantumTape)): List of quantum tapes that implement the identity.
         custom_quantum_cost (dict): Optional, quantum cost that overrides the default cost dictionary.
 
     Returns:
-        pennylane.QNode or qfunc or tuple[List[.QuantumTape], function]: If a QNode is passed,
-        it returns a QNode with the transform added to its transform program.
-        If a tape is passed, returns a tuple containing a list of
-        quantum tapes to be evaluated, and a function to be applied to these
-        tape executions.
+        qnode (QNode) or quantum function (Callable) or tuple[List[QuantumTape], function]: The transformed circuit as described in :func:`qml.transform <pennylane.transform>`.
 
     Raises:
         QuantumFunctionError: The pattern provided is not a valid QuantumTape or the pattern contains measurements or
@@ -55,11 +51,24 @@ def pattern_matching_optimization(
 
     **Example**
 
-    First let's consider the following circuit where we want to replace sequence of two ``pennylane.S`` gates with a
+    >>> dev = qml.device('default.qubit', wires=5)
+
+    You can apply the transform directly on a :class:`QNode`. For that, you need first to define a pattern that is to be
+    found in the circuit. We use the following pattern that implements the identity:
+
+    .. code-block:: python
+
+        ops = [qml.S(0), qml.S(0), qml.PauliZ(0)]
+        pattern = qml.tape.QuantumTape(ops)
+
+
+    Let's consider the following circuit where we want to replace a sequence of two ``pennylane.S`` gates with a
     ``pennylane.PauliZ`` gate.
 
     .. code-block:: python
 
+        @partial(pattern_matching_optimization, pattern_tapes = [pattern])
+        @qml.qnode(device=dev)
         def circuit():
             qml.S(wires=0)
             qml.PauliZ(wires=0)
@@ -71,102 +80,114 @@ def pattern_matching_optimization(
             qml.S(wires=2)
             return qml.expval(qml.PauliX(wires=0))
 
-    Therefore we use the following pattern that implements the identity:
-
-    .. code-block:: python
-
-        ops = [qml.S(0), qml.S(0), qml.PauliZ(0)]
-        pattern = qml.tape.QuantumTape(ops)
-
-    For optimizing the circuit given the following template of CNOTs we apply the ``pattern_matching``
-    transform.
-
-    >>> dev = qml.device('default.qubit', wires=5)
-    >>> qnode = qml.QNode(circuit, dev)
-    >>> optimized_qfunc = pattern_matching_optimization(circuit, pattern_tapes=[pattern])
-    >>> optimized_qnode = qml.QNode(optimized_qfunc, dev)
-
-    >>> print(qml.draw(qnode)())
-    0: ──S──Z─╭●──────────┤  <X>
-    1: ──S────╰Z──S─╭●────┤
-    2: ──S──────────╰Z──S─┤
-
-    >>> print(qml.draw(optimized_qnode)())
-    0: ──S†─╭●────┤  <X>
-    1: ──Z──╰Z─╭●─┤
-    2: ──Z─────╰Z─┤
-
-    Note that with this pattern we also replace a ``pennylane.S``, ``pennylane.PauliZ`` sequence by
-    ``Adjoint(S)``. If one would like avoiding this, it possible to give a custom
-    quantum cost dictionary with a negative cost for ``pennylane.PauliZ``.
-
-    >>> my_cost = {"PauliZ": -1 , "S": 1, "Adjoint(S)": 1}
-    >>> optimized_qfunc = pattern_matching_optimization(circuit, pattern_tapes=[pattern], custom_quantum_cost=my_cost)
-    >>> optimized_qnode = qml.QNode(optimized_qfunc, dev)
-
-    >>> print(qml.draw(optimized_qnode)())
-    0: ──S──Z─╭●────┤  <X>
-    1: ──Z────╰Z─╭●─┤
-    2: ──Z───────╰Z─┤
-
-    Now we can consider a more complicated example with the following quantum circuit to be optimized
-
-    .. code-block:: python
-
-        def circuit():
-            qml.Toffoli(wires=[3, 4, 0])
-            qml.CNOT(wires=[1, 4])
-            qml.CNOT(wires=[2, 1])
-            qml.Hadamard(wires=3)
-            qml.PauliZ(wires=1)
-            qml.CNOT(wires=[2, 3])
-            qml.Toffoli(wires=[2, 3, 0])
-            qml.CNOT(wires=[1, 4])
-            return qml.expval(qml.PauliX(wires=0))
-
-    We define a pattern that implement the identity:
-
-    .. code-block:: python
-
-        ops = [
-            qml.CNOT(wires=[1, 2]),
-            qml.CNOT(wires=[0, 1]),
-            qml.CNOT(wires=[1, 2]),
-            qml.CNOT(wires=[0, 1]),
-            qml.CNOT(wires=[0, 2]),
-        ]
-        tape = qml.tape.QuantumTape(ops)
-
-    For optimizing the circuit given the given following pattern of CNOTs we apply the `pattern_matching`
-    transform.
-
-    >>> dev = qml.device('default.qubit', wires=5)
-    >>> qnode = qml.QNode(circuit, dev)
-    >>> optimized_qfunc = pattern_matching_optimization(circuit, pattern_tapes=[pattern])
-    >>> optimized_qnode = qml.QNode(optimized_qfunc, dev)
-
-    In our case, it is possible to find three CNOTs and replace this pattern with only two CNOTs and therefore
-    optimizing the circuit. The number of CNOTs in the circuit is reduced by one.
-
-    >>> qml.specs(qnode)()["resources"].gate_types["CNOT"]
-    4
-
-    >>> qml.specs(optimized_qnode)()["resources"].gate_types["CNOT"]
-    3
-
-    >>> print(qml.draw(qnode)())
-    0: ─╭X──────────╭X────┤  <X>
-    1: ─│──╭●─╭X──Z─│──╭●─┤
-    2: ─│──│──╰●─╭●─├●─│──┤
-    3: ─├●─│───H─╰X─╰●─│──┤
-    4: ─╰●─╰X──────────╰X─┤
-
-    >>> print(qml.draw(optimized_qnode)())
-    0: ─╭X──────────╭X─┤  <X>
-    1: ─│─────╭X──Z─│──┤
-    2: ─│──╭●─╰●─╭●─├●─┤
-    3: ─├●─│───H─╰X─╰●─┤
-    4: ─╰●─╰X──────────┤
+    During the call of the circuit, it is first optimized (if possible) and then executed.
+
+    >>> circuit()
+
+    .. details::
+        :title: Usage Details
+
+        .. code-block:: python
+
+            def circuit():
+                qml.S(wires=0)
+                qml.PauliZ(wires=0)
+                qml.S(wires=1)
+                qml.CZ(wires=[0, 1])
+                qml.S(wires=1)
+                qml.S(wires=2)
+                qml.CZ(wires=[1, 2])
+                qml.S(wires=2)
+                return qml.expval(qml.PauliX(wires=0))
+
+        For optimizing the circuit given the following template of CNOTs we apply the ``pattern_matching``
+        transform.
+
+        >>> qnode = qml.QNode(circuit, dev)
+        >>> optimized_qfunc = pattern_matching_optimization(pattern_tapes=[pattern])(circuit)
+        >>> optimized_qnode = qml.QNode(optimized_qfunc, dev)
+
+        >>> print(qml.draw(qnode)())
+        0: ──S──Z─╭●──────────┤  <X>
+        1: ──S────╰Z──S─╭●────┤
+        2: ──S──────────╰Z──S─┤
+
+        >>> print(qml.draw(optimized_qnode)())
+        0: ──S†─╭●────┤  <X>
+        1: ──Z──╰Z─╭●─┤
+        2: ──Z─────╰Z─┤
+
+        Note that with this pattern we also replace a ``pennylane.S``, ``pennylane.PauliZ`` sequence by
+        ``Adjoint(S)``. If one would like avoiding this, it possible to give a custom
+        quantum cost dictionary with a negative cost for ``pennylane.PauliZ``.
+
+        >>> my_cost = {"PauliZ": -1 , "S": 1, "Adjoint(S)": 1}
+        >>> optimized_qfunc = pattern_matching_optimization(circuit, pattern_tapes=[pattern], custom_quantum_cost=my_cost)
+        >>> optimized_qnode = qml.QNode(optimized_qfunc, dev)
+
+        >>> print(qml.draw(optimized_qnode)())
+        0: ──S──Z─╭●────┤  <X>
+        1: ──Z────╰Z─╭●─┤
+        2: ──Z───────╰Z─┤
+
+        Now we can consider a more complicated example with the following quantum circuit to be optimized
+
+        .. code-block:: python
+
+            def circuit():
+                qml.Toffoli(wires=[3, 4, 0])
+                qml.CNOT(wires=[1, 4])
+                qml.CNOT(wires=[2, 1])
+                qml.Hadamard(wires=3)
+                qml.PauliZ(wires=1)
+                qml.CNOT(wires=[2, 3])
+                qml.Toffoli(wires=[2, 3, 0])
+                qml.CNOT(wires=[1, 4])
+                return qml.expval(qml.PauliX(wires=0))
+
+        We define a pattern that implement the identity:
+
+        .. code-block:: python
+
+            ops = [
+                qml.CNOT(wires=[1, 2]),
+                qml.CNOT(wires=[0, 1]),
+                qml.CNOT(wires=[1, 2]),
+                qml.CNOT(wires=[0, 1]),
+                qml.CNOT(wires=[0, 2]),
+            ]
+            tape = qml.tape.QuantumTape(ops)
+
+        For optimizing the circuit given the given following pattern of CNOTs we apply the `pattern_matching`
+        transform.
+
+        >>> dev = qml.device('default.qubit', wires=5)
+        >>> qnode = qml.QNode(circuit, dev)
+        >>> optimized_qfunc = pattern_matching_optimization(circuit, pattern_tapes=[pattern])
+        >>> optimized_qnode = qml.QNode(optimized_qfunc, dev)
+
+        In our case, it is possible to find three CNOTs and replace this pattern with only two CNOTs and therefore
+        optimizing the circuit. The number of CNOTs in the circuit is reduced by one.
+
+        >>> qml.specs(qnode)()["resources"].gate_types["CNOT"]
+        4
+
+        >>> qml.specs(optimized_qnode)()["resources"].gate_types["CNOT"]
+        3
+
+        >>> print(qml.draw(qnode)())
+        0: ─╭X──────────╭X────┤  <X>
+        1: ─│──╭●─╭X──Z─│──╭●─┤
+        2: ─│──│──╰●─╭●─├●─│──┤
+        3: ─├●─│───H─╰X─╰●─│──┤
+        4: ─╰●─╰X──────────╰X─┤
+
+        >>> print(qml.draw(optimized_qnode)())
+        0: ─╭X──────────╭X─┤  <X>
+        1: ─│─────╭X──Z─│──┤
+        2: ─│──╭●─╰●─╭●─├●─┤
+        3: ─├●─│───H─╰X─╰●─┤
+        4: ─╰●─╰X──────────┤
 
     .. seealso:: :func:`~.pattern_matching`
 
diff --git a/pennylane/transforms/optimization/remove_barrier.py b/pennylane/transforms/optimization/remove_barrier.py
index 150c5fab1..708d863f7 100644
--- a/pennylane/transforms/optimization/remove_barrier.py
+++ b/pennylane/transforms/optimization/remove_barrier.py
@@ -16,7 +16,7 @@
 from typing import Sequence, Callable
 
 from pennylane.tape import QuantumTape
-from pennylane.transforms.core import transform
+from pennylane.transforms import transform
 
 
 @transform
@@ -24,44 +24,58 @@ def remove_barrier(tape: QuantumTape) -> (Sequence[QuantumTape], Callable):
     """Quantum transform to remove Barrier gates.
 
     Args:
-        qfunc (function): A quantum function.
+        tape (QNode or QuantumTape or Callable): A quantum circuit.
 
     Returns:
-        pennylane.QNode or qfunc or tuple[List[.QuantumTape], function]: If a QNode is passed,
-        it returns a QNode with the transform added to its transform program.
-        If a tape is passed, returns a tuple containing a list of
-        quantum tapes to be evaluated, and a function to be applied to these
-        tape executions.
+        qnode (QNode) or quantum function (Callable) or tuple[List[.QuantumTape], function]: The transformed circuit as described in :func:`qml.transform <pennylane.transform>`.
 
     **Example**
 
-    Consider the following quantum function:
+    The transform can be applied on :class:`QNode` directly.
 
     .. code-block:: python
 
-        def qfunc(x, y):
+        @remove_barrier
+        @qml.qnode(device=dev)
+        def circuit(x, y):
             qml.Hadamard(wires=0)
             qml.Hadamard(wires=1)
             qml.Barrier(wires=[0,1])
             qml.PauliX(wires=0)
             return qml.expval(qml.PauliZ(0))
 
-    The circuit before optimization:
+    The barrier is then removed before execution.
 
-    >>> dev = qml.device('default.qubit', wires=2)
-    >>> qnode = qml.QNode(qfunc, dev)
-    >>> print(qml.draw(qnode)(1, 2))
-        0: ──H──╭||──X──┤ ⟨Z⟩
-        1: ──H──╰||─────┤
+    .. details::
+        :title: Usage Details
 
+        Consider the following quantum function:
 
-    We can remove the Barrier by running the ``remove_barrier`` transform:
+        .. code-block:: python
 
-    >>> optimized_qfunc = remove_barrier(qfunc)
-    >>> optimized_qnode = qml.QNode(optimized_qfunc, dev)
-    >>> print(qml.draw(optimized_qnode)(1, 2))
-       0: ──H──X──┤ ⟨Z⟩
-       1: ──H─────┤
+            def qfunc(x, y):
+                qml.Hadamard(wires=0)
+                qml.Hadamard(wires=1)
+                qml.Barrier(wires=[0,1])
+                qml.PauliX(wires=0)
+                return qml.expval(qml.PauliZ(0))
+
+        The circuit before optimization:
+
+        >>> dev = qml.device('default.qubit', wires=2)
+        >>> qnode = qml.QNode(qfunc, dev)
+        >>> print(qml.draw(qnode)(1, 2))
+            0: ──H──╭||──X──┤ ⟨Z⟩
+            1: ──H──╰||─────┤
+
+
+        We can remove the Barrier by running the ``remove_barrier`` transform:
+
+        >>> optimized_qfunc = remove_barrier(qfunc)
+        >>> optimized_qnode = qml.QNode(optimized_qfunc, dev)
+        >>> print(qml.draw(optimized_qnode)(1, 2))
+           0: ──H──X──┤ ⟨Z⟩
+           1: ──H─────┤
 
     """
     # Make a working copy of the list to traverse
diff --git a/pennylane/transforms/optimization/single_qubit_fusion.py b/pennylane/transforms/optimization/single_qubit_fusion.py
index 21ef18ab6..e3b89a9e1 100644
--- a/pennylane/transforms/optimization/single_qubit_fusion.py
+++ b/pennylane/transforms/optimization/single_qubit_fusion.py
@@ -16,7 +16,7 @@
 from typing import Sequence, Callable
 
 from pennylane.tape import QuantumTape
-from pennylane.transforms.core import transform
+from pennylane.transforms import transform
 from pennylane.ops.qubit import Rot
 from pennylane.math import allclose, stack, is_abstract
 from pennylane.queuing import QueuingManager
@@ -36,7 +36,7 @@ def single_qubit_fusion(
     (on the same qubit) with that property defined will be fused into one ``Rot``.
 
     Args:
-        tape (QuantumTape): A quantum tape.
+        tape (QNode or QuantumTape or Callable): A quantum circuit.
         atol (float): An absolute tolerance for which to apply a rotation after
             fusion. After fusion of gates, if the fused angles :math:`\theta` are such that
             :math:`|\theta|\leq \text{atol}`, no rotation gate will be applied.
@@ -45,18 +45,18 @@ def single_qubit_fusion(
             be fused will be fused.
 
     Returns:
-        pennylane.QNode or qfunc or tuple[List[.QuantumTape], function]: If a QNode is passed,
-        it returns a QNode with the transform added to its transform program.
-        If a tape is passed, returns a tuple containing a list of
-        quantum tapes to be evaluated, and a function to be applied to these
-        tape executions.
+        qnode (QNode) or quantum function (Callable) or tuple[List[QuantumTape], function]: The transformed circuit as described in :func:`qml.transform <pennylane.transform>`.
 
     **Example**
 
-    Consider the following quantum function.
+    >>> dev = qml.device('default.qubit', wires=1)
+
+    You can apply the transform directly on :class:`QNode`:
 
     .. code-block:: python
 
+        @single_qubit_fusion
+        @qml.qnode(device=dev)
         def qfunc(r1, r2):
             qml.Hadamard(wires=0)
             qml.Rot(*r1, wires=0)
@@ -65,20 +65,36 @@ def single_qubit_fusion(
             qml.RZ(r2[0], wires=0)
             return qml.expval(qml.PauliX(0))
 
-    The circuit before optimization:
+    The single qubit gates are fused before execution.
 
-    >>> dev = qml.device('default.qubit', wires=1)
-    >>> qnode = qml.QNode(qfunc, dev)
-    >>> print(qml.draw(qnode)([0.1, 0.2, 0.3], [0.4, 0.5, 0.6]))
-    0: ──H──Rot(0.1, 0.2, 0.3)──Rot(0.4, 0.5, 0.6)──RZ(0.1)──RZ(0.4)──┤ ⟨X⟩
+    .. details::
+        :title: Usage Details
+
+        Consider the following quantum function.
+
+        .. code-block:: python
+
+            def qfunc(r1, r2):
+                qml.Hadamard(wires=0)
+                qml.Rot(*r1, wires=0)
+                qml.Rot(*r2, wires=0)
+                qml.RZ(r1[0], wires=0)
+                qml.RZ(r2[0], wires=0)
+                return qml.expval(qml.PauliX(0))
+
+        The circuit before optimization:
+
+        >>> qnode = qml.QNode(qfunc, dev)
+        >>> print(qml.draw(qnode)([0.1, 0.2, 0.3], [0.4, 0.5, 0.6]))
+        0: ──H──Rot(0.1, 0.2, 0.3)──Rot(0.4, 0.5, 0.6)──RZ(0.1)──RZ(0.4)──┤ ⟨X⟩
 
-    Full single-qubit gate fusion allows us to collapse this entire sequence into a
-    single ``qml.Rot`` rotation gate.
+        Full single-qubit gate fusion allows us to collapse this entire sequence into a
+        single ``qml.Rot`` rotation gate.
 
-    >>> optimized_qfunc = single_qubit_fusion(qfunc)
-    >>> optimized_qnode = qml.QNode(optimized_qfunc, dev)
-    >>> print(qml.draw(optimized_qnode)([0.1, 0.2, 0.3], [0.4, 0.5, 0.6]))
-    0: ──Rot(3.57, 2.09, 2.05)──┤ ⟨X⟩
+        >>> optimized_qfunc = single_qubit_fusion(qfunc)
+        >>> optimized_qnode = qml.QNode(optimized_qfunc, dev)
+        >>> print(qml.draw(optimized_qnode)([0.1, 0.2, 0.3], [0.4, 0.5, 0.6]))
+        0: ──Rot(3.57, 2.09, 2.05)──┤ ⟨X⟩
 
     """
     # Make a working copy of the list to traverse
diff --git a/pennylane/transforms/optimization/undo_swaps.py b/pennylane/transforms/optimization/undo_swaps.py
index be35951cd..2f8dbcf3d 100644
--- a/pennylane/transforms/optimization/undo_swaps.py
+++ b/pennylane/transforms/optimization/undo_swaps.py
@@ -16,7 +16,7 @@
 # pylint: disable=too-many-branches
 from typing import Sequence, Callable
 
-from pennylane.transforms.core import transform
+from pennylane.transforms import transform
 
 from pennylane.tape import QuantumTape
 from pennylane.wires import Wires
@@ -29,22 +29,22 @@ def undo_swaps(tape: QuantumTape) -> (Sequence[QuantumTape], Callable):
     to left through the circuit changing the position of the qubits accordingly.
 
     Args:
-        tape (QuantumTape): A quantum tape.
+        tape (QNode or QuantumTape or Callable): A quantum circuit.
 
     Returns:
-        pennylane.QNode or qfunc or tuple[List[.QuantumTape], function]: If a QNode is passed,
-        it returns a QNode with the transform added to its transform program.
-        If a tape is passed, returns a tuple containing a list of
-        quantum tapes to be evaluated, and a function to be applied to these
-        tape executions.
+        qnode (QNode) or quantum function (Callable) or tuple[List[QuantumTape], function]: The transformed circuit as described in :func:`qml.transform <pennylane.transform>`.
 
     **Example**
 
-    Consider the following quantum function:
+    >>> dev = qml.device('default.qubit', wires=3)
+
+    You can apply the transform directly on a :class:`QNode`
 
     .. code-block:: python
 
-        def qfunc():
+        @undo_swaps
+        @qml.qnode(device=dev)
+        def circuit():
             qml.Hadamard(wires=0)
             qml.PauliX(wires=1)
             qml.SWAP(wires=[0,1])
@@ -52,24 +52,41 @@ def undo_swaps(tape: QuantumTape) -> (Sequence[QuantumTape], Callable):
             qml.PauliY(wires=0)
             return qml.expval(qml.PauliZ(0))
 
-    The circuit before optimization:
+    The SWAP gates are removed before execution.
 
-    >>> dev = qml.device('default.qubit', wires=3)
-    >>> qnode = qml.QNode(qfunc, dev)
-    >>> print(qml.draw(qnode)())
-        0: ──H──╭SWAP──╭SWAP──Y──┤ ⟨Z⟩
-        1: ──X──╰SWAP──│─────────┤
-        2: ────────────╰SWAP─────┤
+    .. details::
+        :title: Usage Details
+
+        Consider the following quantum function:
+
+        .. code-block:: python
+
+            def qfunc():
+                qml.Hadamard(wires=0)
+                qml.PauliX(wires=1)
+                qml.SWAP(wires=[0,1])
+                qml.SWAP(wires=[0,2])
+                qml.PauliY(wires=0)
+                return qml.expval(qml.PauliZ(0))
+
+        The circuit before optimization:
+
+        >>> dev = qml.device('default.qubit', wires=3)
+        >>> qnode = qml.QNode(qfunc, dev)
+        >>> print(qml.draw(qnode)())
+            0: ──H──╭SWAP──╭SWAP──Y──┤ ⟨Z⟩
+            1: ──X──╰SWAP──│─────────┤
+            2: ────────────╰SWAP─────┤
 
 
-    We can remove the SWAP gates by running the ``undo_swap`` transform:
+        We can remove the SWAP gates by running the ``undo_swap`` transform:
 
-    >>> optimized_qfunc = undo_swaps(qfunc)
-    >>> optimized_qnode = qml.QNode(optimized_qfunc, dev)
-    >>> print(qml.draw(optimized_qnode)())
-        0: ──Y──┤ ⟨Z⟩
-        1: ──H──┤
-        2: ──X──┤
+        >>> optimized_qfunc = undo_swaps(qfunc)
+        >>> optimized_qnode = qml.QNode(optimized_qfunc, dev)
+        >>> print(qml.draw(optimized_qnode)())
+            0: ──Y──┤ ⟨Z⟩
+            1: ──H──┤
+            2: ──X──┤
 
     """
     # Make a working copy of the list to traverse
diff --git a/pennylane/transforms/qcut/cutcircuit.py b/pennylane/transforms/qcut/cutcircuit.py
index ae110eed6..b4199c8e6 100644
--- a/pennylane/transforms/qcut/cutcircuit.py
+++ b/pennylane/transforms/qcut/cutcircuit.py
@@ -21,7 +21,7 @@ from typing import Callable, Optional, Union, Sequence
 import pennylane as qml
 from pennylane.measurements import ExpectationMP
 from pennylane.tape import QuantumTape
-from pennylane.transforms.core import transform
+from pennylane.transforms import transform
 from pennylane.wires import Wires
 
 from .cutstrategy import CutStrategy
@@ -90,7 +90,7 @@ def cut_circuit(
         Only circuits that return a single expectation value are supported.
 
     Args:
-        tape (QuantumTape): the tape of the full circuit to be cut
+        tape (QNode or QuantumTape): the quantum circuit to be cut
         auto_cutter (Union[bool, Callable]): Toggle for enabling automatic cutting with the default
             :func:`~.kahypar_cut` partition method. Can also pass a graph partitioning function that
             takes an input graph and returns a list of edges to be cut based on a given set of
@@ -112,10 +112,10 @@ def cut_circuit(
             :func:`~.find_and_place_cuts` and :func:`~.kahypar_cut` for the available arguments.
 
     Returns:
-        Callable: Function which accepts the same arguments as the QNode.
-        When called, this function will perform a process tomography of the
-        partitioned circuit fragments and combine the results via tensor
-        contractions.
+        qnode (QNode) or tuple[List[QuantumTape], function]:
+
+        The transformed circuit as described in :func:`qml.transform <pennylane.transform>`. Executing this circuit
+        will perform a process tomography of the partitioned circuit fragments and combine the results via tensor contractions.
 
     **Example**
 
diff --git a/pennylane/transforms/qcut/montecarlo.py b/pennylane/transforms/qcut/montecarlo.py
index 2ad95bb14..da76ad2a5 100644
--- a/pennylane/transforms/qcut/montecarlo.py
+++ b/pennylane/transforms/qcut/montecarlo.py
@@ -26,7 +26,7 @@ from pennylane import numpy as np
 from pennylane.measurements import SampleMP
 from pennylane.queuing import AnnotatedQueue
 from pennylane.tape import QuantumScript, QuantumTape
-from pennylane.transforms.core import transform
+from pennylane.transforms import transform
 from pennylane.wires import Wires
 
 from .cutstrategy import CutStrategy
@@ -87,7 +87,7 @@ def cut_circuit_mc(
     an expectation value will be evaluated.
 
     Args:
-        tape (QuantumTape): the tape of the full circuit to be cut
+        tape (QNode or QuantumTape): the quantum circuit to be cut.
         classical_processing_fn (callable): A classical postprocessing function to be applied to
             the reconstructed bitstrings. The expected input is a bitstring; a flat array of length ``wires``,
             and the output should be a single number within the interval :math:`[-1, 1]`.
@@ -111,9 +111,10 @@ def cut_circuit_mc(
             :func:`~.find_and_place_cuts` and :func:`~.kahypar_cut` for the available arguments.
 
     Returns:
-        Callable: Function which accepts the same arguments as the QNode.
-        When called, this function will sample from the partitioned circuit fragments
-        and combine the results using a Monte Carlo method.
+        qnode (QNode) or tuple[List[QuantumTape], function]:
+
+        The transformed circuit as described in :func:`qml.transform <pennylane.transform>`. Executing this circuit
+        will sample from the partitioned circuit fragments and combine the results using a Monte Carlo method.
 
     **Example**
 
diff --git a/pennylane/transforms/sign_expand/sign_expand.py b/pennylane/transforms/sign_expand/sign_expand.py
index 58d3681dc..f92824813 100644
--- a/pennylane/transforms/sign_expand/sign_expand.py
+++ b/pennylane/transforms/sign_expand/sign_expand.py
@@ -19,7 +19,7 @@ from typing import Sequence, Callable
 
 import pennylane as qml
 from pennylane import numpy as np
-from pennylane.transforms.core import transform
+from pennylane.transforms import transform
 
 
 def controlled_pauli_evolution(theta, wires, pauli_word, controls):
@@ -208,7 +208,7 @@ def sign_expand(  # pylint: disable=too-many-arguments
     For the calculation of variances, one assumes an even distribution of shots among the groups.
 
     Args:
-        tape (.QuantumTape): the tape used when calculating the expectation value of the Hamiltonian
+        tape (QNode or QuantumTape): the quantum circuit used when calculating the expectation value of the Hamiltonian
         circuit (bool): Toggle the calculation of the analytical Xi decomposition or if True
           constructs the circuits of the approximate sign decomposition to measure the expectation
           value
@@ -219,9 +219,7 @@ def sign_expand(  # pylint: disable=too-many-arguments
           Hadamard test and the quantum signal processing part on, have to be wires on the device
 
     Returns:
-        tuple[list[.QuantumTape], function]: Returns a tuple containing a list of quantum tapes
-          to be evaluated, and a function to be applied to these tape executions to compute the
-          expectation value.
+        qnode (pennylane.QNode) or tuple[List[.QuantumTape], function]: The transformed circuit as described in :func:`qml.transform <pennylane.transform>`.
 
     **Example**
 
diff --git a/pennylane/transforms/split_non_commuting.py b/pennylane/transforms/split_non_commuting.py
index bd2fe2c9a..06719ff80 100644
--- a/pennylane/transforms/split_non_commuting.py
+++ b/pennylane/transforms/split_non_commuting.py
@@ -21,7 +21,7 @@ from functools import reduce
 import pennylane as qml
 from pennylane.measurements import ProbabilityMP, SampleMP
 
-from pennylane.transforms.core import transform
+from pennylane.transforms import transform
 
 
 @transform
@@ -30,15 +30,11 @@ def split_non_commuting(tape: qml.tape.QuantumTape) -> (Sequence[qml.tape.Quantu
     Splits a qnode measuring non-commuting observables into groups of commuting observables.
 
     Args:
-        qnode (pennylane.QNode or .QuantumTape): quantum tape or QNode that contains a list of
+        tape (QNode or QuantumTape or Callable): A circuit that contains a list of
             non-commuting observables to measure.
 
     Returns:
-        qnode (pennylane.QNode) or tuple[List[.QuantumTape], function]: If a QNode is passed,
-        it returns a QNode capable of handling non-commuting groups.
-        If a tape is passed, returns a tuple containing a list of
-        quantum tapes to be evaluated, and a function to be applied to these
-        tape executions to restore the ordering of the inputs.
+        qnode (QNode) or tuple[List[QuantumTape], function]: The transformed circuit as described in :func:`qml.transform <pennylane.transform>`.
 
     **Example**
 
diff --git a/pennylane/transforms/transpile.py b/pennylane/transforms/transpile.py
index cd09e47d3..2ddd3a49c 100644
--- a/pennylane/transforms/transpile.py
+++ b/pennylane/transforms/transpile.py
@@ -5,7 +5,7 @@ from typing import List, Union, Sequence, Callable
 
 import networkx as nx
 
-from pennylane.transforms.core import transform
+from pennylane.transforms import transform
 from pennylane import Hamiltonian
 from pennylane.operation import Tensor
 from pennylane.ops import __all__ as all_ops
@@ -26,16 +26,12 @@ def transpile(
         is passed which contains these types of measurements, a ``NotImplementedError`` will be raised.
 
     Args:
-        tape (QuantumTape): A quantum tape.
+        tape (QNode or QuantumTape or Callable): A quantum tape.
         coupling_map (list[tuple(int, int)] or nx.Graph): Either a list of tuples(int, int) or an instance of
             `networkx.Graph` specifying the couplings between different qubits.
 
     Returns:
-        pennylane.QNode or qfunc or tuple[List[.QuantumTape], function]: If a QNode is passed,
-        it returns a QNode with the transform added to its transform program.
-        If a tape is passed, returns a tuple containing a list of
-        quantum tapes to be evaluated, and a function to be applied to these
-        tape executions.
+        qnode (QNode) or quantum function (Callable) or tuple[List[.QuantumTape], function]: The transformed circuit as described in :func:`qml.transform <pennylane.transform>`.
 
     **Example**
 
@@ -73,7 +69,7 @@ def transpile(
     with the circuit, to the transpile function to get a circuit which can be executed for the specified coupling map:
 
     >>> dev = qml.device('default.qubit', wires=[0, 1, 2, 3])
-    >>> transpiled_circuit = qml.transforms.transpile(coupling_map=[(0, 1), (1, 3), (3, 2), (2, 0)])(circuit)
+    >>> transpiled_circuit = qml.transforms.transpile(circuit, coupling_map=[(0, 1), (1, 3), (3, 2), (2, 0)])
     >>> transpiled_qnode = qml.QNode(transpiled_circuit, dev)
     >>> print(qml.draw(transpiled_qnode)())
     0: ─╭●────────────────╭●─┤ ╭Probs
diff --git a/pennylane/transforms/unitary_to_rot.py b/pennylane/transforms/unitary_to_rot.py
index 36ddc3f4b..23b4251d4 100644
--- a/pennylane/transforms/unitary_to_rot.py
+++ b/pennylane/transforms/unitary_to_rot.py
@@ -18,7 +18,7 @@ from typing import Sequence, Callable
 
 from pennylane.queuing import QueuingManager
 from pennylane.tape import QuantumTape
-from pennylane.transforms.core import transform
+from pennylane.transforms import transform
 
 import pennylane as qml
 from pennylane.transforms.decompositions import one_qubit_decomposition, two_qubit_decomposition
@@ -41,14 +41,10 @@ def unitary_to_rot(tape: QuantumTape) -> (Sequence[QuantumTape], Callable):
         operations. See usage details below.
 
     Args:
-        tape (QuantumTape): a quantum tape
+        tape (QNode or QuantumTape or Callable): A quantum circuit.
 
     Returns:
-        pennylane.QNode or qfunc or tuple[List[.QuantumTape], function]: If a QNode is passed,
-        it returns a QNode with the transform added to its transform program.
-        If a tape is passed, returns a tuple containing a list of
-        quantum tapes to be evaluated, and a function to be applied to these
-        tape executions.
+        qnode (QNode) or quantum function (Callable) or tuple[List[QuantumTape], function]: The transformed circuit as described in :func:`qml.transform <pennylane.transform>`.
 
     **Example**
 
diff --git a/pennylane/transforms/zx/converter.py b/pennylane/transforms/zx/converter.py
index d005322f9..3236d2353 100644
--- a/pennylane/transforms/zx/converter.py
+++ b/pennylane/transforms/zx/converter.py
@@ -21,7 +21,7 @@ import numpy as np
 import pennylane as qml
 from pennylane.tape import QuantumScript, QuantumTape
 from pennylane.transforms.op_transforms import OperationTransformError
-from pennylane.transforms.core import transform
+from pennylane.transforms import transform
 from pennylane.wires import Wires
 
 
@@ -54,10 +54,16 @@ def to_zx(tape, expand_measurements=False):  # pylint: disable=unused-argument
     The graph can be optimized and transformed by well-known ZX-calculus reductions.
 
     Args:
-        tape(QuantumTape, Operation): The PennyLane quantum circuit.
+        tape(QNode or QuantumTape or Callable or Operation): The PennyLane quantum circuit.
         expand_measurements(bool): The expansion will be applied on measurements that are not in the Z-basis and
             rotations will be added to the operations.
 
+    Returns:
+        graph (pyzx.Graph) or qnode (QNode) or quantum function (Callable) or tuple[List[QuantumTape], function]:
+
+        The transformed circuit as described in :func:`qml.transform <pennylane.transform>`. Executing this circuit
+        will provide the ZX graph in the form of a PyZX graph.
+
     **Example**
 
     You can use the transform decorator directly on your :class:`~.QNode`, quantum function and executing it will produce a
@@ -227,7 +233,8 @@ def to_zx(tape, expand_measurements=False):  # pylint: disable=unused-argument
 
             wires = qml.wires.Wires([4, 3, 0, 2, 1])
             wires_map = dict(zip(tape_opt.wires, wires))
-            tape_opt_reorder = qml.map_wires(input=tape_opt, wire_map=wires_map)[0][0]
+            tapes_opt_reorder, fn = qml.map_wires(input=tape_opt, wire_map=wires_map)[0][0]
+            tape_opt_reorder = fn(tapes_opt_reorder)
 
             @qml.qnode(device=dev)
             def mod_5_4():


Test patch:
diff --git a/tests/transforms/test_experimental/test_transform_dispatcher.py b/tests/transforms/test_experimental/test_transform_dispatcher.py
index cb5d3df81..548b27631 100644
--- a/tests/transforms/test_experimental/test_transform_dispatcher.py
+++ b/tests/transforms/test_experimental/test_transform_dispatcher.py
@@ -620,3 +620,18 @@ class TestTransformDispatcher:  # pylint: disable=too-many-public-methods
         ):
             dispatched_transform = transform(valid_transform, expand_transform=valid_transform)
             dispatched_transform(device, index=0)
+
+    def test_sphinx_build(self, monkeypatch):
+        """Test that transforms are not created during Sphinx builds"""
+        monkeypatch.setenv("SPHINX_BUILD", "1")
+
+        with pytest.warns(UserWarning, match="Transforms have been disabled, as a Sphinx"):
+
+            @qml.transforms.core.transform
+            def custom_transform(  # pylint:disable=unused-variable
+                tape: qml.tape.QuantumTape, index: int
+            ) -> (Sequence[qml.tape.QuantumTape], Callable):
+                """A valid transform."""
+                tape = tape.copy()
+                tape._ops.pop(index)  # pylint:disable=protected-access
+                return [tape], lambda x: x
diff --git a/tests/transforms/test_specs.py b/tests/transforms/test_specs.py
index 0904ddb99..be31aaf13 100644
--- a/tests/transforms/test_specs.py
+++ b/tests/transforms/test_specs.py
@@ -54,9 +54,7 @@ class TestSpecsTransform:
 
         if diff_method == "parameter-shift":
             assert info["num_gradient_executions"] == 0
-            assert (
-                info["gradient_fn"] == "pennylane.transforms.core.transform_dispatcher.param_shift"
-            )
+            assert info["gradient_fn"] == "pennylane.gradients.parameter_shift.param_shift"
 
     @pytest.mark.parametrize(
         "diff_method, len_info", [("backprop", 11), ("parameter-shift", 12), ("adjoint", 11)]
@@ -187,8 +185,8 @@ class TestSpecsTransform:
 
         with pytest.warns(UserWarning, match="gradient of a tape with no trainable parameters"):
             info = qml.specs(circuit)()
-        assert info["diff_method"] == "pennylane.transforms.core.transform_dispatcher.param_shift"
-        assert info["gradient_fn"] == "pennylane.transforms.core.transform_dispatcher.param_shift"
+        assert info["diff_method"] == "pennylane.gradients.parameter_shift.param_shift"
+        assert info["gradient_fn"] == "pennylane.gradients.parameter_shift.param_shift"
 
     def test_custom_gradient_transform(self):
         """Test that a custom gradient transform is properly labelled"""
@@ -203,8 +201,8 @@ class TestSpecsTransform:
             return qml.probs(wires=0)
 
         info = qml.specs(circuit)()
-        assert info["diff_method"] == "pennylane.transforms.core.transform_dispatcher.my_transform"
-        assert info["gradient_fn"] == "pennylane.transforms.core.transform_dispatcher.my_transform"
+        assert info["diff_method"] == "test_specs.my_transform"
+        assert info["gradient_fn"] == "test_specs.my_transform"
 
     @pytest.mark.parametrize(
         "device,num_wires",