Repository: PennyLaneAI/pennylane
Pull request #3539 (2022-12-15 03:00:25)

Daily rc sync to master 2022-12-15
Automatic sync from the release candidate to master during a feature freeze.

codecov[bot]: # [Codecov](https://codecov.io/gh/PennyLaneAI/pennylane/pull/3539?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI) Report
> Merging [#3539](https://codecov.io/gh/PennyLaneAI/pennylane/pull/3539?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI) (0b60322) into [master](https://codecov.io/gh/PennyLaneAI/pennylane/commit/7b986365da132bac883e9474a83d970f7c35c52b?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI) (7b98636) will **decrease** coverage by `0.00%`.
> The diff coverage is `100.00%`.

```diff
@@            Coverage Diff             @@
##           master    #3539      +/-   ##
==========================================
- Coverage   99.87%   99.87%   -0.01%     
==========================================
  Files         311      311              
  Lines       27905    27903       -2     
==========================================
- Hits        27869    27867       -2     
  Misses         36       36              
```


| [Impacted Files](https://codecov.io/gh/PennyLaneAI/pennylane/pull/3539?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI) | Coverage Δ | |
|---|---|---|
| [pennylane/transforms/batch\_transform.py](https://codecov.io/gh/PennyLaneAI/pennylane/pull/3539/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI#diff-cGVubnlsYW5lL3RyYW5zZm9ybXMvYmF0Y2hfdHJhbnNmb3JtLnB5) | `100.00% <ø> (ø)` | |
| [pennylane/transforms/condition.py](https://codecov.io/gh/PennyLaneAI/pennylane/pull/3539/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI#diff-cGVubnlsYW5lL3RyYW5zZm9ybXMvY29uZGl0aW9uLnB5) | `100.00% <ø> (ø)` | |
| [pennylane/transforms/insert\_ops.py](https://codecov.io/gh/PennyLaneAI/pennylane/pull/3539/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI#diff-cGVubnlsYW5lL3RyYW5zZm9ybXMvaW5zZXJ0X29wcy5weQ==) | `100.00% <ø> (ø)` | |
| [pennylane/transforms/metric\_tensor.py](https://codecov.io/gh/PennyLaneAI/pennylane/pull/3539/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI#diff-cGVubnlsYW5lL3RyYW5zZm9ybXMvbWV0cmljX3RlbnNvci5weQ==) | `100.00% <ø> (ø)` | |
| [pennylane/transforms/qcut/tapes.py](https://codecov.io/gh/PennyLaneAI/pennylane/pull/3539/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI#diff-cGVubnlsYW5lL3RyYW5zZm9ybXMvcWN1dC90YXBlcy5weQ==) | `100.00% <ø> (ø)` | |
| [pennylane/\_device.py](https://codecov.io/gh/PennyLaneAI/pennylane/pull/3539/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI#diff-cGVubnlsYW5lL19kZXZpY2UucHk=) | `100.00% <100.00%> (ø)` | |
| [pennylane/\_qubit\_device.py](https://codecov.io/gh/PennyLaneAI/pennylane/pull/3539/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI#diff-cGVubnlsYW5lL19xdWJpdF9kZXZpY2UucHk=) | `99.69% <100.00%> (ø)` | |
| [pennylane/measurements/\_\_init\_\_.py](https://codecov.io/gh/PennyLaneAI/pennylane/pull/3539/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI#diff-cGVubnlsYW5lL21lYXN1cmVtZW50cy9fX2luaXRfXy5weQ==) | `100.00% <100.00%> (ø)` | |
| [pennylane/measurements/classical\_shadow.py](https://codecov.io/gh/PennyLaneAI/pennylane/pull/3539/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI#diff-cGVubnlsYW5lL21lYXN1cmVtZW50cy9jbGFzc2ljYWxfc2hhZG93LnB5) | `100.00% <100.00%> (ø)` | |
| [pennylane/measurements/measurements.py](https://codecov.io/gh/PennyLaneAI/pennylane/pull/3539/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI#diff-cGVubnlsYW5lL21lYXN1cmVtZW50cy9tZWFzdXJlbWVudHMucHk=) | `100.00% <100.00%> (ø)` | |
| ... and [10 more](https://codecov.io/gh/PennyLaneAI/pennylane/pull/3539/diff?src=pr&el=tree-more&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI) | |

Help us with your feedback. Take ten seconds to tell us [how you rate us](https://about.codecov.io/nps?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI). Have a feature suggestion? [Share it here.](https://app.codecov.io/gh/feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI)


Patch:
diff --git a/doc/code/qml_measurements.rst b/doc/code/qml_measurements.rst
index eacb8978e..122d36520 100644
--- a/doc/code/qml_measurements.rst
+++ b/doc/code/qml_measurements.rst
@@ -3,6 +3,14 @@ qml.measurements
 
 .. currentmodule:: pennylane.measurements
 
+.. warning::
+
+    Unless you are a PennyLane or plugin developer, you likely do not need
+    to use these classes directly.
+
+    See the :doc:`main measurements page <../introduction/measurements>` for
+    details on available measurements.
+
 .. automodapi:: pennylane.measurements
     :no-heading:
     :include-all-objects:
diff --git a/doc/development/deprecations.rst b/doc/development/deprecations.rst
index 4c427538f..3a4e42765 100644
--- a/doc/development/deprecations.rst
+++ b/doc/development/deprecations.rst
@@ -16,8 +16,8 @@ Pending deprecations
   A new argument ``seed`` has been added, which defaults to ``None`` and can contain an integer with the 
   wanted seed.
 
-  - Still accessible in v0.27
-  - Will be removed in v0.28
+  - Still accessible in v0.28
+  - Will be removed in v0.29
 
 * The ``grouping`` module is deprecated. The functionality has been moved and
   reorganized in the new ``pauli`` module under ``pauli/utils.py`` or ``pauli/grouping/``.
@@ -55,7 +55,7 @@ Pending deprecations
 * ``qml.ExpvalCost`` has been deprecated, and usage will now raise a warning.
   
   - Deprecated in v0.24
-  - Will be removed in v0.28
+  - Will be removed in v0.29
 
   Instead, it is recommended to simply
   pass Hamiltonians to the ``qml.expval`` function inside QNodes:
diff --git a/doc/development/guide/architecture.rst b/doc/development/guide/architecture.rst
index d6997a270..9c75ca403 100644
--- a/doc/development/guide/architecture.rst
+++ b/doc/development/guide/architecture.rst
@@ -99,12 +99,14 @@ MeasurementProcess
 ******************
 
 While the :class:`~.Operator` class describes a physical system and its dynamics,
-the :class:`pennylane.measure.MeasurementProcess` class describes how we extract information from the quantum system.
-The measurement functions such as :func:`~pennylane.expval` create an instance of this class.
+the :class:`pennylane.measurement.MeasurementProcess` class describes how we extract information from the quantum system.
+Each measurement in pennylane has a specific class that inherits from :class:`pennylane.measurement.MeasurementProcess`.
+The measurement functions such as :func:`~pennylane.expval` create an instance of its corresponding
+class (:class:`pennylane.measurements.ExpectationMP`). 
 
 >>> m = qml.expval(qml.PauliZ("a"))
 >>> type(m)
-<class 'pennylane.measure.MeasurementProcess'>
+<class 'pennylane.measurements.expval.ExpectationMP'>
 
 An instance of the :class:`~.MeasurementProcess` class specifies the measured observables,
 which are themselves operators.
diff --git a/doc/releases/changelog-0.28.0.md b/doc/releases/changelog-0.28.0.md
index f48f357a7..379ddcf59 100644
--- a/doc/releases/changelog-0.28.0.md
+++ b/doc/releases/changelog-0.28.0.md
@@ -193,7 +193,7 @@
 
 * Support custom measurement processes:
   - `SampleMeasurement`, `StateMeasurement` and `CustomMeasurement` classes have been added.
-    They contain an abstract method to process samples/quantum states/quantum scripts. These classes
+    They contain an abstract method to process samples/quantum states/quantum tapes. These classes
     make it easier for users to define their own `MeasurementProcess` by compartmentalizing the different
     types of measurements into three simple categories. 
 
@@ -732,7 +732,7 @@
   to
 
   ```python
-  def statistics(self, circuit: QuantumScript, shot_range=None, bin_size=None):
+  def statistics(self, circuit: QuantumTape, shot_range=None, bin_size=None):
   ```
 
   [(#3421)](https://github.com/PennyLaneAI/pennylane/pull/3421)
diff --git a/pennylane/_device.py b/pennylane/_device.py
index daa0c7352..bc359c266 100644
--- a/pennylane/_device.py
+++ b/pennylane/_device.py
@@ -40,7 +40,7 @@ from pennylane.measurements import (
 )
 from pennylane.operation import Observable, Operation, Tensor
 from pennylane.ops import Hamiltonian, Sum
-from pennylane.tape import QuantumScript
+from pennylane.tape import QuantumScript, QuantumTape
 from pennylane.wires import WireError, Wires
 
 ShotTuple = namedtuple("ShotTuple", ["shots", "copies"])
@@ -604,8 +604,7 @@ class Device(abc.ABC):
         function accepts a queuable object (including a PennyLane operation
         and observable) and returns ``True`` if supported by the device."""
         return qml.BooleanFn(
-            lambda obj: not isinstance(obj, qml.tape.QuantumScript)
-            and self.supports_operation(obj.name)
+            lambda obj: not isinstance(obj, QuantumScript) and self.supports_operation(obj.name)
         )
 
     def custom_expand(self, fn):
@@ -699,7 +698,7 @@ class Device(abc.ABC):
 
         return self.default_expand_fn(circuit, max_expansion=max_expansion)
 
-    def batch_transform(self, circuit: QuantumScript):
+    def batch_transform(self, circuit: QuantumTape):
         """Apply a differentiable batch transform for preprocessing a circuit
         prior to execution. This method is called directly by the QNode, and
         should be overwritten if the device requires a transform that
diff --git a/pennylane/_qubit_device.py b/pennylane/_qubit_device.py
index 060e34879..00daadd6c 100644
--- a/pennylane/_qubit_device.py
+++ b/pennylane/_qubit_device.py
@@ -61,7 +61,7 @@ from pennylane.measurements import (
     VnEntropyMP,
 )
 from pennylane.operation import operation_derivative
-from pennylane.tape import QuantumScript
+from pennylane.tape import QuantumScript, QuantumTape
 from pennylane.wires import Wires
 
 
@@ -232,7 +232,7 @@ class QubitDevice(Device):
         When overriding the logic of a :class:`~pennylane.measurements.MeasurementTransform`, the
         method defined by the device should only have a single argument:
 
-        * qscript: quantum script to transform
+        * tape: quantum tape to transform
 
     **Example:**
 
@@ -397,7 +397,7 @@ class QubitDevice(Device):
 
         return results
 
-    def execute(self, circuit: QuantumScript, **kwargs):
+    def execute(self, circuit: QuantumTape, **kwargs):
         """Execute a queue of quantum operations on the device and then
         measure the given observables.
 
@@ -478,7 +478,7 @@ class QubitDevice(Device):
 
         return results
 
-    def shot_vec_statistics(self, circuit: QuantumScript):
+    def shot_vec_statistics(self, circuit: QuantumTape):
         """Process measurement results from circuit execution using a device
         with a shot vector and return statistics.
 
@@ -556,7 +556,7 @@ class QubitDevice(Device):
 
         return tuple(results)
 
-    def _multi_meas_with_counts_shot_vec(self, circuit: QuantumScript, shot_tuple, r):
+    def _multi_meas_with_counts_shot_vec(self, circuit: QuantumTape, shot_tuple, r):
         """Auxiliary function of the shot_vec_statistics and execute_new
         functions for post-processing the results of multiple measurements at
         least one of which was a counts measurement.
@@ -721,7 +721,7 @@ class QubitDevice(Device):
 
     # pylint: disable=too-many-statements
     def statistics(
-        self, observables=None, shot_range=None, bin_size=None, circuit: QuantumScript = None
+        self, observables=None, shot_range=None, bin_size=None, circuit: QuantumTape = None
     ):
         """Process measurement results from circuit execution and return statistics.
 
@@ -729,7 +729,7 @@ class QubitDevice(Device):
         density matrices.
 
         Args:
-            circuit (~.tape.QuantumScript): the quantum script currently being executed
+            circuit (~.tape.QuantumTape): the quantum tape currently being executed
             shot_range (tuple[int]): 2-tuple of integers specifying the range of samples
                 to use. If not specified, all samples are used.
             bin_size (int): Divides the shot range into bins of size ``bin_size``, and
@@ -775,7 +775,7 @@ class QubitDevice(Device):
             else:
                 warnings.warn(
                     message="Using a list of observables in ``QubitDevice.statistics`` is "
-                    "deprecated. Please use a ``QuantumScript`` instead.",
+                    "deprecated. Please use a ``QuantumTape`` instead.",
                     category=UserWarning,
                 )
                 measurements = observables
@@ -796,7 +796,7 @@ class QubitDevice(Device):
             # Check if there is an overriden version of the measurement process
             if method := getattr(self, self.measurement_map[type(m)], False):
                 if isinstance(m, MeasurementTransform):
-                    results.append(method(qscript=circuit))
+                    results.append(method(tape=circuit))
                 else:
                     results.append(method(m, shot_range=shot_range, bin_size=bin_size))
             # TODO: Remove return_type when `observables` argument is removed from this method
@@ -908,7 +908,7 @@ class QubitDevice(Device):
                 results.append(self.shadow_expval(obs, circuit=circuit))
 
             elif isinstance(m, MeasurementTransform):
-                results.append(m.process(qscript=circuit, device=self))
+                results.append(m.process(tape=circuit, device=self))
 
             elif isinstance(m, (SampleMeasurement, StateMeasurement)):
                 results.append(self._measure(m, shot_range=shot_range, bin_size=bin_size))
@@ -963,14 +963,14 @@ class QubitDevice(Device):
             samples=self._samples, wire_order=self.wires, shot_range=shot_range, bin_size=bin_size
         )
 
-    def _statistics_new(self, circuit: QuantumScript, shot_range=None, bin_size=None):
+    def _statistics_new(self, circuit: QuantumTape, shot_range=None, bin_size=None):
         """Process measurement results from circuit execution and return statistics.
 
         This includes returning expectation values, variance, samples, probabilities, states, and
         density matrices.
 
         Args:
-            circuit (~.tape.QuantumScript): the quantum script currently being executed
+            circuit (~.tape.QuantumTape): the quantum tape currently being executed
             shot_range (tuple[int]): 2-tuple of integers specifying the range of samples
                 to use. If not specified, all samples are used.
             bin_size (int): Divides the shot range into bins of size ``bin_size``, and
@@ -1022,7 +1022,7 @@ class QubitDevice(Device):
             # Check if there is an overriden version of the measurement process
             if method := getattr(self, self.measurement_map[type(m)], False):
                 if isinstance(m, MeasurementTransform):
-                    result = method(qscript=circuit)
+                    result = method(tape=circuit)
                 else:
                     result = method(m, shot_range=shot_range, bin_size=bin_size)
             # 1. Based on the measurement type, compute statistics
@@ -1123,7 +1123,7 @@ class QubitDevice(Device):
                 result = self.shadow_expval(obs, circuit=circuit)
 
             elif isinstance(m, MeasurementTransform):
-                result = m.process(qscript=circuit, device=self)
+                result = m.process(tape=circuit, device=self)
 
             elif isinstance(m, (SampleMeasurement, StateMeasurement)):
                 result = self._measure(m, shot_range=shot_range, bin_size=bin_size)
@@ -1931,7 +1931,7 @@ class QubitDevice(Device):
         )
 
     def adjoint_jacobian(
-        self, tape: QuantumScript, starting_state=None, use_device_state=False
+        self, tape: QuantumTape, starting_state=None, use_device_state=False
     ):  # pylint: disable=too-many-statements
         """Implements the adjoint method outlined in
         `Jones and Gacon <https://arxiv.org/abs/2009.02823>`__ to differentiate an input tape.
@@ -1951,7 +1951,7 @@ class QubitDevice(Device):
               :class:`~.Hamiltonian` or :class:`~.Hermitian`.
 
         Args:
-            tape (.QuantumScript): circuit that the function takes the gradient of
+            tape (.QuantumTape): circuit that the function takes the gradient of
 
         Keyword Args:
             starting_state (tensor_like): post-forward pass state to start execution with. It should be
diff --git a/pennylane/measurements/__init__.py b/pennylane/measurements/__init__.py
index 6b23db1ab..e02f895db 100644
--- a/pennylane/measurements/__init__.py
+++ b/pennylane/measurements/__init__.py
@@ -11,8 +11,151 @@
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 # See the License for the specific language governing permissions and
 # limitations under the License.
-"""
-This module contains measurements supported by PennyLane.
+r"""
+This module contains all the measurements supported by PennyLane.
+
+Description
+-----------
+
+Measurements
+~~~~~~~~~~~~
+The :class:`MeasurementProcess` class serves as a base class for measurements, and is inherited
+from by the :class:`SampleMeasurement`, :class:`StateMeasurement` and :class:`MeasurementTransform`
+classes. These classes are subclassed to implement measurements in PennyLane.
+
+* Each :class:`SampleMeasurement` subclass represents a sample-based measurement, which contains a
+  :meth:`SampleMeasurement.process_samples` method that processes the sequence of samples generated
+  by the device. This method should always have the same arguments:
+
+  * samples (Sequence[complex]): computational basis samples generated for all wires
+  * wire_order (Wires): wires determining the subspace that ``samples`` acts on
+  * shot_range (tuple[int]): 2-tuple of integers specifying the range of samples to use. If not
+    specified, all samples are used.
+  * bin_size (int): Divides the shot range into bins of size ``bin_size``, and returns the
+    measurement statistic separately over each bin. If not provided, the entire shot range is treated
+    as a single bin.
+
+  See :class:`CountsMP` for an example.
+
+* Each :class:`StateMeasurement` subclass represents a state-based measurement, which contains a
+  :meth:`StateMeasurement.process_state` method that processes the quantum state generated by the
+  device. This method should always have the same arguments:
+
+  * state (Sequence[complex]): quantum state
+  * wire_order (Wires): wires determining the subspace that ``state`` acts on; a matrix of dimension
+    :math:`2^n` acts on a subspace of :math:`n` wires
+
+  See :class:`StateMP` for an example.
+
+* Each :class:`MeasurementTransform` subclass represents a measurement process that requires
+  the application of a batch transform, which contains a :meth:`MeasurementTransform.process` method
+  that converts the given quantum tape into a batch of quantum tapes and executes them using the
+  device. This method should always have the same arguments:
+
+  * tape (QuantumTape): quantum tape to transform
+  * device (Device): device used to transform the quantum tape
+
+  The main difference between a :class:`MeasurementTransform` and a
+  :func:`~pennylane.batch_transform` is that a batch transform is tracked by the gradient transform,
+  while a :class:`MeasurementTransform` process isn't.
+
+  See :class:`ClassicalShadowMP` for an example.
+
+.. note::
+
+    A measurement process can inherit from both :class:`SampleMeasurement` and
+    :class:`StateMeasurement` classes, defining the needed logic to process either samples or the
+    quantum state. See :class:`VarianceMP` for an example.
+
+Differentiation
+^^^^^^^^^^^^^^^
+In general, a :class:`MeasurementProcess` is differentiable with respect to a parameter if the domain of
+that parameter is continuous. When using the analytic method of differentiation the output of the
+measurement process must be a real scalar value for it to be differentiable.
+
+Creating custom measurements
+----------------------------
+A custom measurement process can be created by inheriting from any of the classes mentioned above.
+
+The following is an example for a sample-based measurement that computes the number of samples
+obtained of a given state:
+
+.. code-block:: python
+
+    import pennylane as qml
+    from pennylane.measurements import SampleMeasurement
+
+    class CountState(SampleMeasurement):
+        def __init__(self, state: str):
+            self.state = state  # string identifying the state e.g. "0101"
+            wires = list(range(len(state)))
+            super().__init__(wires=wires)
+
+        def process_samples(self, samples, wire_order, shot_range, bin_size):
+            counts_mp = qml.counts(wires=self._wires)
+            counts = counts_mp.process_samples(samples, wire_order, shot_range, bin_size)
+            return counts.get(self.state, 0)
+
+        def __copy__(self):
+            return CountState(state=self.state)
+
+.. note::
+
+    The ``__copy__`` method needs to be overriden when new arguments are added into the ``__init__``
+    method.
+
+The measurement process in this example uses the :func:`~pennylane.counts` function, which is a
+measurement process which returns a dictionary containing the number of times each quantum
+state has been sampled.
+
+We can now execute the new measurement in a :class:`~pennylane.QNode`. Let's use a simple circuit
+so that we can verify our results mathematically.
+
+.. code-block:: python
+
+    dev = qml.device("default.qubit", wires=1, shots=10000)
+
+    @qml.qnode(dev)
+    def circuit(x):
+        qml.RX(x, wires=0)
+        return CountState(state="1")
+
+The quantum state before the measurement will be:
+
+.. math:: \psi = R_x(\theta) \begin{bmatrix} 1 \\ 0 \end{bmatrix} = \begin{bmatrix}
+                \cos(\theta/2) & -i\sin(\theta/2) \\
+                -i\sin(\theta/2) & \cos(\theta/2)
+            \end{bmatrix} \begin{bmatrix} 1 \\ 0 \end{bmatrix} = \begin{bmatrix}
+                \cos(\theta/2) \\ -i\sin(\theta/2)
+            \end{bmatrix}
+
+When :math:`\theta = 1.23`, the probability of obtaining the state
+:math:`\begin{bmatrix} 1 \\ 0 \end{bmatrix}` is :math:`\sin^2(\theta/2) = 0.333`. Using 10000 shots
+we should obtain the excited state 3333 times approximately.
+
+>>> circuit(1.23)
+tensor(3303., requires_grad=True)
+
+Given that the measurement process returns a real scalar value, we can differentiate it
+using the analytic method.
+
+We know from the previous analysis that the analytic result of the measurement process is
+:math:`r(\theta) = \text{nshots} \cdot \sin^2(\theta/2)`.
+
+The gradient of the measurement process is
+:math:`\frac{\partial r}{\partial \theta} = \text{nshots} \sin(\theta/2) \cos(\theta/2)`.
+
+When :math:`\theta = 1.23`, :math:`\frac{\partial r}{\partial \theta} = 4712.444`
+
+>>> x = qml.numpy.array(1.23, requires_grad=True)
+>>> qml.grad(circuit)(x)
+4715.000000000001
+
+.. note::
+
+    In PennyLane we use functions to define measurements (e.g. :func:`counts`). These
+    functions will return an instance of the corresponding measurement process
+    (e.g. :class:`CountsMP`). This decision is just for design purposes.
 """
 from .classical_shadow import ClassicalShadowMP, ShadowExpvalMP, classical_shadow, shadow_expval
 from .counts import CountsMP, counts
diff --git a/pennylane/measurements/classical_shadow.py b/pennylane/measurements/classical_shadow.py
index 18ea5ae99..f53e87ef5 100644
--- a/pennylane/measurements/classical_shadow.py
+++ b/pennylane/measurements/classical_shadow.py
@@ -237,7 +237,7 @@ class ClassicalShadowMP(MeasurementTransform):
         self.seed = seed
         super().__init__(*args, **kwargs)
 
-    def process(self, qscript, device):
+    def process(self, tape, device):
         """
         Returns the measured bits and recipes in the classical shadow protocol.
 
@@ -257,14 +257,14 @@ class ClassicalShadowMP(MeasurementTransform):
         Pauli measurements have shape ``(T, n)``.
 
         This implementation is device-agnostic and works by executing single-shot
-        quantum scripts containing randomized Pauli observables. Devices should override this
+        quantum tapes containing randomized Pauli observables. Devices should override this
         if they can offer cleaner or faster implementations.
 
         .. seealso:: :func:`~pennylane.classical_shadow`
 
         Args:
-            qscript (QuantumScript): the quantum script to be processed
-            device (Device): the device used to process the quantum script
+            tape (QuantumTape): the quantum tape to be processed
+            device (Device): the device used to process the quantum tape
 
         Returns:
             tensor_like[int]: A tensor with shape ``(2, T, n)``, where the first row represents
@@ -298,7 +298,7 @@ class ClassicalShadowMP(MeasurementTransform):
                 ]
 
                 device.reset()
-                device.apply(qscript.operations, rotations=qscript.diagonalizing_gates + rotations)
+                device.apply(tape.operations, rotations=tape.diagonalizing_gates + rotations)
 
                 outcomes[t] = device.generate_samples()[0][mapped_wires]
 
@@ -354,10 +354,8 @@ class ShadowExpvalMP(MeasurementTransform):
         self.k = k
         super().__init__(*args, **kwargs)
 
-    def process(self, qscript, device):
-        bits, recipes = qml.classical_shadow(wires=self.wires, seed=self.seed).process(
-            qscript, device
-        )
+    def process(self, tape, device):
+        bits, recipes = qml.classical_shadow(wires=self.wires, seed=self.seed).process(tape, device)
         shadow = qml.shadows.ClassicalShadow(bits, recipes, wire_map=self.wires.tolist())
         return shadow.expval(self.H, self.k)
 
diff --git a/pennylane/measurements/measurements.py b/pennylane/measurements/measurements.py
index be129ea2f..d24b23186 100644
--- a/pennylane/measurements/measurements.py
+++ b/pennylane/measurements/measurements.py
@@ -375,7 +375,7 @@ class MeasurementProcess(ABC):
         rotation and a measurement in the computational basis.
 
         Returns:
-            .QuantumScript: a quantum script containing the operations
+            .QuantumTape: a quantum tape containing the operations
             required to diagonalize the observable
 
         **Example:**
@@ -389,18 +389,18 @@ class MeasurementProcess(ABC):
 
         Expanding this out:
 
-        >>> qscript = m.expand()
+        >>> tape = m.expand()
 
-        We can see that the resulting script has the qubit unitary applied,
+        We can see that the resulting tape has the qubit unitary applied,
         and a measurement process with no observable, but the eigenvalues
         specified:
 
-        >>> print(qscript.operations)
+        >>> print(tape.operations)
         [QubitUnitary(array([[-0.89442719,  0.4472136 ],
               [ 0.4472136 ,  0.89442719]]), wires=['a'])]
-        >>> print(qscript.measurements[0].eigvals())
+        >>> print(tape.measurements[0].eigvals())
         [0. 5.]
-        >>> print(qscript.measurements[0].obs)
+        >>> print(tape.measurements[0].obs)
         None
         """
         if self.obs is None:
@@ -633,21 +633,21 @@ class StateMeasurement(MeasurementProcess):
 
 
 class MeasurementTransform(MeasurementProcess):
-    """Measurement process that applies a transform into the given quantum script. This transform
+    """Measurement process that applies a transform into the given quantum tape. This transform
     is carried out inside the gradient black box, thus is not tracked by the gradient transform.
 
     Any class inheriting from ``MeasurementTransform`` should define its own ``process`` method,
     which should have the following arguments:
 
-    * qscript (QuantumScript): quantum script to transform
-    * device (Device): device used to transform the quantum script
+    * tape (QuantumTape): quantum tape to transform
+    * device (Device): device used to transform the quantum tape
     """
 
     @abstractmethod
-    def process(self, qscript, device):
-        """Process the given quantum script.
+    def process(self, tape, device):
+        """Process the given quantum tape.
 
         Args:
-            qscript (QuantumScript): quantum script to transform
-            device (Device): device used to transform the quantum script
+            tape (QuantumTape): quantum tape to transform
+            device (Device): device used to transform the quantum tape
         """
diff --git a/pennylane/ops/functions/map_wires.py b/pennylane/ops/functions/map_wires.py
index 3c7953dc0..9ef4633cb 100644
--- a/pennylane/ops/functions/map_wires.py
+++ b/pennylane/ops/functions/map_wires.py
@@ -22,11 +22,11 @@ from pennylane.measurements import MeasurementProcess
 from pennylane.operation import Operator
 from pennylane.qnode import QNode
 from pennylane.queuing import QueuingManager
-from pennylane.tape import QuantumScript, make_qscript
+from pennylane.tape import QuantumScript, make_qscript, QuantumTape
 
 
 def map_wires(
-    input: Union[Operator, MeasurementProcess, QuantumScript, QNode, Callable],
+    input: Union[Operator, MeasurementProcess, QuantumTape, QNode, Callable],
     wire_map: dict,
     queue=False,
     replace=False,
@@ -35,15 +35,15 @@ def map_wires(
     wire map.
 
     Args:
-        input (.Operator, pennylane.QNode, .QuantumScript, or Callable): an operator, quantum node,
-            quantum script, or function that applies quantum operations
+        input (.Operator, pennylane.QNode, .QuantumTape, or Callable): an operator, quantum node,
+            quantum tape, or function that applies quantum operations
         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, .QuantumScript, or Callable): input with changed wires
+        (.Operator, pennylane.QNode, .QuantumTape, or Callable): input with changed wires
 
     .. note::
 
@@ -103,7 +103,7 @@ def map_wires(
         measurements = [qml.map_wires(m, wire_map) for m in input.measurements]
         prep = [qml.map_wires(p, wire_map) for p in input._prep]  # pylint: disable=protected-access
 
-        return QuantumScript(ops=ops, measurements=measurements, prep=prep)
+        return input.__class__(ops=ops, measurements=measurements, prep=prep)
 
     if callable(input):
 
diff --git a/pennylane/ops/functions/simplify.py b/pennylane/ops/functions/simplify.py
index 89abafa9f..f99a1f624 100644
--- a/pennylane/ops/functions/simplify.py
+++ b/pennylane/ops/functions/simplify.py
@@ -23,19 +23,19 @@ from pennylane.measurements import MeasurementProcess
 from pennylane.operation import Operator
 from pennylane.qnode import QNode
 from pennylane.queuing import QueuingManager
-from pennylane.tape import QuantumScript, make_qscript
+from pennylane.tape import QuantumScript, make_qscript, QuantumTape
 
 
-def simplify(input: Union[Operator, MeasurementProcess, QuantumScript, QNode, Callable]):
+def simplify(input: Union[Operator, MeasurementProcess, QuantumTape, QNode, Callable]):
     """Simplifies an operator, tape, qnode or quantum function by reducing its arithmetic depth
     or number of rotation parameters.
 
     Args:
-        input (.Operator, pennylane.QNode, .QuantumScript, or Callable): an operator, quantum node,
+        input (.Operator, pennylane.QNode, .QuantumTape, or Callable): an operator, quantum node,
             tape or function that applies quantum operations
 
     Returns:
-        (.Operator, pennylane.QNode, .QuantumScript, or Callable): Simplified input.
+        (.Operator, pennylane.QNode, .QuantumTape, or Callable): Simplified input.
 
     **Example**
 
@@ -91,7 +91,7 @@ def simplify(input: Union[Operator, MeasurementProcess, QuantumScript, QNode, Ca
 
     if isinstance(input, QuantumScript):
         # pylint: disable=protected-access
-        return QuantumScript(
+        return input.__class__(
             [op.simplify() for op in input._ops],
             [m.simplify() for m in input.measurements],
             [op.simplify() for op in input._prep],
diff --git a/pennylane/qnode.py b/pennylane/qnode.py
index 79d50ed25..d8a04f021 100644
--- a/pennylane/qnode.py
+++ b/pennylane/qnode.py
@@ -26,7 +26,7 @@ import pennylane as qml
 from pennylane import Device
 from pennylane.interfaces import INTERFACE_MAP, SUPPORTED_INTERFACES, set_shots
 from pennylane.measurements import ClassicalShadowMP, CountsMP, MidMeasureMP
-from pennylane.tape import QuantumScript, make_qscript
+from pennylane.tape import QuantumTape, make_qscript
 
 
 class QNode:
@@ -36,7 +36,7 @@ class QNode:
     (corresponding to a :ref:`variational circuit <glossary_variational_circuit>`)
     and the computational device it is executed on.
 
-    The QNode calls the quantum function to construct a :class:`~.QuantumScript` instance representing
+    The QNode calls the quantum function to construct a :class:`~.QuantumTape` instance representing
     the quantum circuit.
 
     Args:
@@ -699,7 +699,7 @@ class QNode:
         )
 
     @property
-    def tape(self) -> QuantumScript:
+    def tape(self) -> QuantumTape:
         """The quantum tape"""
         return self._tape
 
diff --git a/pennylane/shadows/transforms.py b/pennylane/shadows/transforms.py
index 7fca68f27..5bfeb14fe 100644
--- a/pennylane/shadows/transforms.py
+++ b/pennylane/shadows/transforms.py
@@ -20,11 +20,11 @@ from itertools import product
 import pennylane as qml
 import pennylane.numpy as np
 from pennylane.measurements import ClassicalShadowMP
-from pennylane.tape import QuantumScript
+from pennylane.tape import QuantumScript, QuantumTape
 
 
 @qml.batch_transform
-def _replace_obs(tape: QuantumScript, obs, *args, **kwargs):
+def _replace_obs(tape: QuantumTape, obs, *args, **kwargs):
     """
     Tape transform to replace the measurement processes with the given one
     """
@@ -42,7 +42,7 @@ def _replace_obs(tape: QuantumScript, obs, *args, **kwargs):
 
         # queue the new observable
         obs(*args, **kwargs)
-    qscript = qml.tape.QuantumScript.from_queue(q)
+    qscript = QuantumScript.from_queue(q)
 
     def processing_fn(res):
         if qml.active_return():
diff --git a/pennylane/tape/tape.py b/pennylane/tape/tape.py
index 84456398d..a9fa37381 100644
--- a/pennylane/tape/tape.py
+++ b/pennylane/tape/tape.py
@@ -32,12 +32,11 @@ class TapeError(ValueError):
 
 def _err_msg_for_some_meas_not_qwc(measurements):
     """Error message for the case when some operators measured on the same wire are not qubit-wise commuting."""
-    msg = (
+    return (
         "Only observables that are qubit-wise commuting "
         "Pauli words can be returned on the same wire, "
         f"some of the following measurements do not commute:\n{measurements}"
     )
-    return msg
 
 
 def _validate_computational_basis_sampling(measurements):
@@ -79,11 +78,11 @@ def _validate_computational_basis_sampling(measurements):
 
 
 # TODO: move this function to its own file and rename
-def expand_tape(qscript, depth=1, stop_at=None, expand_measurements=False):
+def expand_tape(tape, depth=1, stop_at=None, expand_measurements=False):
     """Expand all objects in a tape to a specific depth.
 
     Args:
-        qscript (QuantumScript): The Quantum Script to expand
+        tape (QuantumTape): The tape to expand
         depth (int): the depth the tape should be expanded
         stop_at (Callable): A function which accepts a queue object,
             and returns ``True`` if this object should *not* be expanded.
@@ -92,10 +91,10 @@ def expand_tape(qscript, depth=1, stop_at=None, expand_measurements=False):
             to basis rotations and computational basis measurements.
 
     Returns:
-        QuantumScript: The expanded version of ``qscript``.
+        QuantumTape: The expanded version of ``tape``.
 
     Raises:
-        QuantumFunctionError: if some observables in the qscript are not qubit-wise commuting
+        QuantumFunctionError: if some observables in the tape are not qubit-wise commuting
 
     **Example**
 
@@ -132,7 +131,7 @@ def expand_tape(qscript, depth=1, stop_at=None, expand_measurements=False):
     RY(0.2, wires=['a'])]
     """
     if depth == 0:
-        return qscript
+        return tape
 
     if stop_at is None:
         # by default expand all objects
@@ -146,20 +145,18 @@ def expand_tape(qscript, depth=1, stop_at=None, expand_measurements=False):
     # Check for observables acting on the same wire. If present, observables must be
     # qubit-wise commuting Pauli words. In this case, the tape is expanded with joint
     # rotations and the observables updated to the computational basis. Note that this
-    # expansion acts on the original qscript in place.
-    if qscript.samples_computational_basis and len(qscript.measurements) > 1:
-        _validate_computational_basis_sampling(qscript.measurements)
+    # expansion acts on the original tape in place.
+    if tape.samples_computational_basis and len(tape.measurements) > 1:
+        _validate_computational_basis_sampling(tape.measurements)
 
-    if qscript._obs_sharing_wires:
+    if tape._obs_sharing_wires:
         with QueuingManager.stop_recording():  # stop recording operations to active context when computing qwc groupings
             try:
-                rotations, diag_obs = qml.pauli.diagonalize_qwc_pauli_words(
-                    qscript._obs_sharing_wires
-                )
-                qscript._obs_sharing_wires = diag_obs
+                rotations, diag_obs = qml.pauli.diagonalize_qwc_pauli_words(tape._obs_sharing_wires)
+                tape._obs_sharing_wires = diag_obs
             except (TypeError, ValueError) as e:
                 if any(
-                    isinstance(m, (ProbabilityMP, SampleMP, CountsMP)) for m in qscript.measurements
+                    isinstance(m, (ProbabilityMP, SampleMP, CountsMP)) for m in tape.measurements
                 ):
                     raise qml.QuantumFunctionError(
                         "Only observables that are qubit-wise commuting "
@@ -170,19 +167,19 @@ def expand_tape(qscript, depth=1, stop_at=None, expand_measurements=False):
                     ) from e
 
                 raise qml.QuantumFunctionError(
-                    _err_msg_for_some_meas_not_qwc(qscript.measurements)
+                    _err_msg_for_some_meas_not_qwc(tape.measurements)
                 ) from e
 
-            qscript._ops.extend(rotations)
+            tape._ops.extend(rotations)
 
-            for o, i in zip(diag_obs, qscript._obs_sharing_wires_id):
-                new_m = qscript.measurements[i].__class__(obs=o)
-                qscript._measurements[i] = new_m
+            for o, i in zip(diag_obs, tape._obs_sharing_wires_id):
+                new_m = tape.measurements[i].__class__(obs=o)
+                tape._measurements[i] = new_m
 
     for queue, new_queue in [
-        (qscript._prep, new_prep),
-        (qscript._ops, new_ops),
-        (qscript._measurements, new_measurements),
+        (tape._prep, new_prep),
+        (tape._ops, new_ops),
+        (tape._measurements, new_measurements),
     ]:
         for obj in queue:
             stop = stop_at(obj)
@@ -194,7 +191,7 @@ def expand_tape(qscript, depth=1, stop_at=None, expand_measurements=False):
 
             if stop:
                 # do not expand out the object; append it to the
-                # new qscript, and continue to the next object in the queue
+                # new tape, and continue to the next object in the queue
                 new_queue.append(obj)
                 continue
 
@@ -208,26 +205,26 @@ def expand_tape(qscript, depth=1, stop_at=None, expand_measurements=False):
                     new_queue.append(obj)
                     continue
 
-            # recursively expand out the newly created qscript
-            expanded_qscript = expand_tape(obj, stop_at=stop_at, depth=depth - 1)
+            # recursively expand out the newly created tape
+            expanded_tape = expand_tape(obj, stop_at=stop_at, depth=depth - 1)
 
-            new_prep.extend(expanded_qscript._prep)
-            new_ops.extend(expanded_qscript._ops)
-            new_measurements.extend(expanded_qscript._measurements)
+            new_prep.extend(expanded_tape._prep)
+            new_ops.extend(expanded_tape._ops)
+            new_measurements.extend(expanded_tape._measurements)
 
     # preserves inheritance structure
-    # if qscript is a QuantumTape, returned object will be a quantum tape
-    new_qscript = qscript.__class__(new_ops, new_measurements, new_prep, _update=False)
+    # if tape is a QuantumTape, returned object will be a quantum tape
+    new_tape = tape.__class__(new_ops, new_measurements, new_prep, _update=False)
 
     # Update circuit info
-    new_qscript.wires = copy.copy(qscript.wires)
-    new_qscript.num_wires = qscript.num_wires
-    new_qscript.is_sampled = qscript.is_sampled
-    new_qscript.all_sampled = qscript.all_sampled
-    new_qscript._batch_size = qscript.batch_size
-    new_qscript._output_dim = qscript.output_dim
-    new_qscript._qfunc_output = qscript._qfunc_output
-    return new_qscript
+    new_tape.wires = copy.copy(tape.wires)
+    new_tape.num_wires = tape.num_wires
+    new_tape.is_sampled = tape.is_sampled
+    new_tape.all_sampled = tape.all_sampled
+    new_tape._batch_size = tape.batch_size
+    new_tape._output_dim = tape.output_dim
+    new_tape._qfunc_output = tape._qfunc_output
+    return new_tape
 
 
 # pylint: disable=too-many-public-methods
@@ -240,10 +237,10 @@ class QuantumTape(QuantumScript, AnnotatedQueue):
         prep (Iterable[Operator]): Any state preparations to perform at the start of the circuit
 
     Keyword Args:
-        name (str): a name given to the quantum script
+        name (str): a name given to the quantum tape
         do_queue=True (bool): Whether or not to queue. Defaults to ``True`` for ``QuantumTape``.
         _update=True (bool): Whether or not to set various properties on initialization. Setting
-            ``_update=False`` reduces computations if the script is only an intermediary step.
+            ``_update=False`` reduces computations if the tape is only an intermediary step.
 
 
     **Example**
diff --git a/pennylane/transforms/adjoint_metric_tensor.py b/pennylane/transforms/adjoint_metric_tensor.py
index 55dcccf02..71339c52e 100644
--- a/pennylane/transforms/adjoint_metric_tensor.py
+++ b/pennylane/transforms/adjoint_metric_tensor.py
@@ -99,7 +99,7 @@ def adjoint_metric_tensor(circuit, device=None, hybrid=True):
           Note also that this makes the metric tensor strictly real-valued.
 
     Args:
-        circuit (.QuantumScript or .QNode): Circuit to compute the metric tensor of
+        circuit (.QuantumTape or .QNode): Circuit to compute the metric tensor of
         device (.Device): Device to use for the adjoint method
         hybrid (bool): Whether to take classical preprocessing into account. Ignored if
             ``circuit`` is a tape.
@@ -161,7 +161,7 @@ def adjoint_metric_tensor(circuit, device=None, hybrid=True):
     if isinstance(circuit, (qml.QNode, qml.ExpvalCost)):
         return _adjoint_metric_tensor_qnode(circuit, device, hybrid)
 
-    raise qml.QuantumFunctionError("The passed object is not a QuantumScript or QNode.")
+    raise qml.QuantumFunctionError("The passed object is not a QuantumTape or QNode.")
 
 
 def _adjoint_metric_tensor_tape(tape, device):
diff --git a/pennylane/transforms/batch_transform.py b/pennylane/transforms/batch_transform.py
index 3e7d3201a..acba5ce17 100644
--- a/pennylane/transforms/batch_transform.py
+++ b/pennylane/transforms/batch_transform.py
@@ -387,7 +387,7 @@ class batch_transform:
         """Applies the batch tape transform to an input tape.
 
         Args:
-            tape (.QuantumScript): the tape to be transformed
+            tape (.QuantumTape): the tape to be transformed
             *args: positional arguments to pass to the tape transform
             **kwargs: keyword arguments to pass to the tape transform
 
@@ -427,7 +427,7 @@ def map_batch_transform(transform, tapes):
     Args:
         transform (.batch_transform): the batch transform
             to be mapped
-        tapes (Sequence[QuantumScript]): The sequence of tapes the batch
+        tapes (Sequence[QuantumTape]): The sequence of tapes the batch
             transform should be applied to. Each tape in the sequence
             is transformed by the batch transform.
 
diff --git a/pennylane/transforms/commutation_dag.py b/pennylane/transforms/commutation_dag.py
index cc6f01f16..f903a641e 100644
--- a/pennylane/transforms/commutation_dag.py
+++ b/pennylane/transforms/commutation_dag.py
@@ -22,7 +22,7 @@ import networkx as nx
 from networkx.drawing.nx_pydot import to_pydot
 
 import pennylane as qml
-from pennylane.tape import QuantumScript, make_qscript
+from pennylane.tape import QuantumScript, make_qscript, QuantumTape
 from pennylane.wires import Wires
 
 
@@ -212,7 +212,7 @@ class CommutationDAG:
 
     """
 
-    def __init__(self, tape: QuantumScript):
+    def __init__(self, tape: QuantumTape):
 
         self.num_wires = len(tape.wires)
         self.node_id = -1
diff --git a/pennylane/transforms/condition.py b/pennylane/transforms/condition.py
index 766f00959..5bb6f0f3b 100644
--- a/pennylane/transforms/condition.py
+++ b/pennylane/transforms/condition.py
@@ -43,7 +43,7 @@ class Conditional(Operation):
         expr (MeasurementValue): the measurement outcome value to consider
         then_op (Operation): the PennyLane operation to apply conditionally
         do_queue (bool): indicates whether the operator should be
-            recorded when created in a qscript context
+            recorded when created in a tape context
         id (str): custom label given to an operator instance,
             can be useful for some applications where the instance has to be identified
     """
diff --git a/pennylane/transforms/hamiltonian_expand.py b/pennylane/transforms/hamiltonian_expand.py
index e22b94aba..d4b42ead4 100644
--- a/pennylane/transforms/hamiltonian_expand.py
+++ b/pennylane/transforms/hamiltonian_expand.py
@@ -20,10 +20,10 @@ from typing import List
 import pennylane as qml
 from pennylane.measurements import ExpectationMP, MeasurementProcess
 from pennylane.ops import SProd, Sum
-from pennylane.tape import QuantumScript
+from pennylane.tape import QuantumScript, QuantumTape
 
 
-def hamiltonian_expand(tape: QuantumScript, group=True):
+def hamiltonian_expand(tape: QuantumTape, group=True):
     r"""
     Splits a tape measuring a Hamiltonian expectation into mutliple tapes of Pauli expectations,
     and provides a function to recombine the results.
@@ -204,20 +204,20 @@ def hamiltonian_expand(tape: QuantumScript, group=True):
 
 
 # pylint: disable=too-many-branches, too-many-statements
-def sum_expand(qscript: QuantumScript, group=True):
-    """Splits a quantum script measuring a Sum expectation into multiple scripts of summand
+def sum_expand(tape: QuantumTape, group=True):
+    """Splits a quantum tape measuring a Sum expectation into multiple tapes of summand
     expectations, and provides a function to recombine the results.
 
     Args:
-        qscript (.QuantumScript): the quantum script used when calculating the expectation value
+        tape (.QuantumTape): the quantum tape used when calculating the expectation value
             of the Hamiltonian
         group (bool): Whether to compute disjoint groups of Pauli observables acting on different
             wires, leading to fewer tapes.
 
     Returns:
-        tuple[list[.QuantumScript], function]: Returns a tuple containing a list of
-        quantum scripts to be evaluated, and a function to be applied to these
-        script executions to compute the expectation value.
+        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.
 
     **Example**
 
@@ -290,12 +290,12 @@ def sum_expand(qscript: QuantumScript, group=True):
     [expval(PauliX(wires=[0]))]
     """
     # Populate these 2 dictionaries with the unique measurement objects, the index of the
-    # initial measurement on the qscript and the coefficient
+    # initial measurement on the tape and the coefficient
     # NOTE: expval(Sum) is expanded into the expectation of each summand
     # NOTE: expval(SProd) is transformed into expval(SProd.base) and the coeff is updated
     measurements_dict = {}  # {m_hash: measurement}
     idxs_coeffs_dict = {}  # {m_hash: [(location_idx, coeff)]}
-    for idx, m in enumerate(qscript.measurements):
+    for idx, m in enumerate(tape.measurements):
         obs = m.obs
         if isinstance(obs, Sum) and isinstance(m, ExpectationMP):
             for summand in obs.operands:
@@ -326,7 +326,7 @@ def sum_expand(qscript: QuantumScript, group=True):
     measurements = list(measurements_dict.values())
     idxs_coeffs = list(idxs_coeffs_dict.values())
 
-    # Create the qscripts, group observables if group==True
+    # Create the tapes, group observables if group==True
     if group:
         m_groups = _group_measurements(measurements)
         # Update ``idxs_coeffs`` list such that it tracks the new ``m_groups`` list of lists
@@ -338,13 +338,12 @@ def sum_expand(qscript: QuantumScript, group=True):
                 tmp_idxs.append([idxs_coeffs[measurements.index(m)] for m in m_group])
         idxs_coeffs = tmp_idxs
         qscripts = [
-            QuantumScript(ops=qscript._ops, measurements=m_group, prep=qscript._prep)
+            QuantumScript(ops=tape._ops, measurements=m_group, prep=tape._prep)
             for m_group in m_groups
         ]
     else:
         qscripts = [
-            QuantumScript(ops=qscript._ops, measurements=[m], prep=qscript._prep)
-            for m in measurements
+            QuantumScript(ops=tape._ops, measurements=[m], prep=tape._prep) for m in measurements
         ]
 
     def processing_fn(expanded_results):
diff --git a/pennylane/transforms/insert_ops.py b/pennylane/transforms/insert_ops.py
index 979c4256b..cd8c92701 100644
--- a/pennylane/transforms/insert_ops.py
+++ b/pennylane/transforms/insert_ops.py
@@ -90,7 +90,7 @@ def insert(
         device which will transform circuits before execution
 
     Raises:
-        QuantumFunctionError: if some observables in the qscript are not qubit-wise commuting
+        QuantumFunctionError: if some observables in the tape are not qubit-wise commuting
         ValueError: if a single operation acting on multiple wires is passed to ``op``
         ValueError: if the requested ``position`` argument is not ``'start'``, ``'end'`` or
             ``'all'`` OR PennyLane Operation
diff --git a/pennylane/transforms/metric_tensor.py b/pennylane/transforms/metric_tensor.py
index 77f779205..080d86d49 100644
--- a/pennylane/transforms/metric_tensor.py
+++ b/pennylane/transforms/metric_tensor.py
@@ -502,10 +502,10 @@ def _get_first_term_tapes(layer_i, layer_j, allow_nonunitary, aux_wire):
             control the controlled-generator operations
 
     Returns:
-        list[pennylane.tape.QuantumScript]: Transformed qscripts that compute the
+        list[pennylane.tape.QuantumTape]: Transformed tapes that compute the
             first term of the metric tensor for the off-diagonal block belonging
             to the input layers
-        list[tuple[int]]: 2-tuple indices assigning the qscripts to metric tensor
+        list[tuple[int]]: 2-tuple indices assigning the tapes to metric tensor
             entries
     """
 
diff --git a/pennylane/transforms/qcut/tapes.py b/pennylane/transforms/qcut/tapes.py
index 07d433a48..1bc4a4270 100644
--- a/pennylane/transforms/qcut/tapes.py
+++ b/pennylane/transforms/qcut/tapes.py
@@ -123,7 +123,7 @@ def graph_to_tape(graph: MultiDiGraph) -> QuantumTape:
         graph (nx.MultiDiGraph): directed multigraph to be converted to a tape
 
     Returns:
-        QuantumTape: the quantum script corresponding to the input graph
+        QuantumTape: the quantum tape corresponding to the input graph
 
     **Example**
 
diff --git a/pennylane/transforms/qfunc_transforms.py b/pennylane/transforms/qfunc_transforms.py
index 45e2ca911..7381daa9d 100644
--- a/pennylane/transforms/qfunc_transforms.py
+++ b/pennylane/transforms/qfunc_transforms.py
@@ -148,7 +148,7 @@ class single_tape_transform:
     def __call__(self, tape, *args, **kwargs):
         with qml.queuing.AnnotatedQueue() as q:
             self.transform_fn(tape, *args, **kwargs)
-        qs = qml.tape.QuantumScript(*qml.queuing.process_queue(q))
+        qs = qml.tape.QuantumScript.from_queue(q)
         for obj, info in q.items():
             qml.queuing.QueuingManager.append(obj, **info)
         return qs
@@ -337,15 +337,15 @@ def qfunc_transform(tape_transform):
 
             def transform(old_qfunc, params):
                 def new_qfunc(*args, **kwargs):
-                    # 1. extract the QuantumScript from the old qfunc, being
+                    # 1. extract the QuantumTape from the old qfunc, being
                     # careful *not* to have it queued.
-                    qscript = make_qscript(old_qfunc)(*args, **kwargs)
+                    tape = make_qscript(old_qfunc)(*args, **kwargs)
 
-                    # 2. transform the qscript
-                    new_script = tape_transform(qscript, params)
+                    # 2. transform the tape
+                    new_tape = tape_transform(tape, params)
 
-                    # 3. queue the *new* qscript to the active queuing context
-                    new_script.queue()
+                    # 3. queue the *new* tape to the active queuing context
+                    new_tape.queue()
                 return new_qfunc
 
         *Note: this is pseudocode; the actual implementation is significantly more complicated!*
diff --git a/pennylane/transforms/zx/converter.py b/pennylane/transforms/zx/converter.py
index 955831af3..61e0e546f 100644
--- a/pennylane/transforms/zx/converter.py
+++ b/pennylane/transforms/zx/converter.py
@@ -47,19 +47,19 @@ class EdgeType:  # pylint: disable=too-few-public-methods
 
 
 @op_transform
-def to_zx(qscript, expand_measurement=False):  # pylint: disable=unused-argument
-    """This transform converts a PennyLane quantum script to a ZX-Graph in the `PyZX framework <https://pyzx.readthedocs.io/en/latest/>`_.
+def to_zx(tape, expand_measurement=False):  # pylint: disable=unused-argument
+    """This transform converts a PennyLane quantum tape to a ZX-Graph in the `PyZX framework <https://pyzx.readthedocs.io/en/latest/>`_.
     The graph can be optimized and transformed by well-known ZX-calculus reductions.
 
     Args:
-        qscript(QuantumScript, Operation): The PennyLane quantum circuit.
+        tape(QuantumTape, 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.
 
     **Example**
 
     You can use the transform decorator directly on your :class:`~.QNode`, quantum function and executing it will produce a
-    PyZX graph. You can also use the transform directly on the :class:`~.QuantumScript`.
+    PyZX graph. You can also use the transform directly on the :class:`~.QuantumTape`.
 
     .. code-block:: python
 
@@ -91,7 +91,7 @@ def to_zx(qscript, expand_measurement=False):  # pylint: disable=unused-argument
     >>> pyzx.draw_matplotlib(g)
     <Figure size 800x200 with 1 Axes>
 
-    Alternatively you can use the transform directly on a quantum script and get PyZX graph.
+    Alternatively you can use the transform directly on a quantum tape and get PyZX graph.
 
     .. code-block:: python
 
@@ -107,8 +107,8 @@ def to_zx(qscript, expand_measurement=False):  # pylint: disable=unused-argument
                 qml.SWAP(wires=[0, 1]),
             ]
 
-        qscript = qml.tape.QuantumScript(operations)
-        g = qml.transforms.to_zx(qscript)
+        tape = qml.tape.QuantumTape(operations)
+        g = qml.transforms.to_zx(tape)
 
     >>> g
     Graph(20 vertices, 23 edges)
@@ -221,15 +221,15 @@ def to_zx(qscript, expand_measurement=False):  # pylint: disable=unused-argument
 
         .. code-block:: python
 
-            qscript_opt = qml.transforms.from_zx(g)
+            tape_opt = qml.transforms.from_zx(g)
 
             wires = qml.wires.Wires([4, 3, 0, 2, 1])
-            wires_map = dict(zip(qscript_opt.wires, wires))
-            qscript_opt_reorder = qml.map_wires(input=qscript_opt, wire_map=wires_map)
+            wires_map = dict(zip(tape_opt.wires, wires))
+            tape_opt_reorder = qml.map_wires(input=tape_opt, wire_map=wires_map)
 
             @qml.qnode(device=dev)
             def mod_5_4():
-                for g in qscript_opt_reorder:
+                for g in tape_opt_reorder:
                     qml.apply(g)
                 return qml.expval(qml.PauliZ(wires=0))
 
@@ -244,11 +244,11 @@ def to_zx(qscript, expand_measurement=False):  # pylint: disable=unused-argument
         Copyright (C) 2018 - Aleks Kissinger and John van de Wetering
     """
     # If it is a simple operation just transform it to a tape
-    return _to_zx(QuantumScript([qscript]))
+    return _to_zx(QuantumScript([tape]))
 
 
 @to_zx.tape_transform
-def _to_zx(qscript, expand_measurements=False):
+def _to_zx(tape, expand_measurements=False):
     """Private function to convert a PennyLane tape to a `PyZX graph <https://pyzx.readthedocs.io/en/latest/>`_ ."""
     # Avoid to make PyZX a requirement for PennyLane.
     try:
@@ -287,30 +287,30 @@ def _to_zx(qscript, expand_measurements=False):
 
     # Map the wires to consecutive wires
 
-    consecutive_wires = Wires(range(len(qscript.wires)))
-    consecutive_wires_map = OrderedDict(zip(qscript.wires, consecutive_wires))
-    qscript = qml.map_wires(input=qscript, wire_map=consecutive_wires_map)
+    consecutive_wires = Wires(range(len(tape.wires)))
+    consecutive_wires_map = OrderedDict(zip(tape.wires, consecutive_wires))
+    tape = qml.map_wires(input=tape, wire_map=consecutive_wires_map)
 
     inputs = []
 
     # Create the qubits in the graph and the qubit mapper
-    for i in range(len(qscript.wires)):
+    for i in range(len(tape.wires)):
         vertex = graph.add_vertex(VertexType.BOUNDARY, i, 0)
         inputs.append(vertex)
         q_mapper.set_prev_vertex(i, vertex)
         q_mapper.set_next_row(i, 1)
         q_mapper.set_qubit(i, i)
 
-    # Expand the qscript to be compatible with PyZX and add rotations first for measurements
+    # Expand the tape to be compatible with PyZX and add rotations first for measurements
     stop_crit = qml.BooleanFn(lambda obj: obj.name in gate_types)
-    qscript = qml.tape.tape.expand_tape(
-        qscript, depth=10, stop_at=stop_crit, expand_measurements=expand_measurements
+    tape = qml.tape.tape.expand_tape(
+        tape, depth=10, stop_at=stop_crit, expand_measurements=expand_measurements
     )
 
     expanded_operations = []
 
     # Define specific decompositions
-    for op in qscript.operations:
+    for op in tape.operations:
         if op.name == "RY":
             theta = op.data[0]
             decomp = [
@@ -323,9 +323,9 @@ def _to_zx(qscript, expand_measurements=False):
         else:
             expanded_operations.append(op)
 
-    expanded_qscript = QuantumScript(expanded_operations, qscript.measurements, [])
+    expanded_tape = QuantumScript(expanded_operations, tape.measurements, [])
 
-    _add_operations_to_graph(expanded_qscript, graph, gate_types, q_mapper, c_mapper)
+    _add_operations_to_graph(expanded_tape, graph, gate_types, q_mapper, c_mapper)
 
     row = max(q_mapper.max_row(), c_mapper.max_row())
 
@@ -344,16 +344,16 @@ def _to_zx(qscript, expand_measurements=False):
     return graph
 
 
-def _add_operations_to_graph(qscript, graph, gate_types, q_mapper, c_mapper):
-    """Add the qscript operation to the PyZX graph."""
-    # Create graph from circuit in the quantum script (operations, measurements)
-    for op in qscript.operations:
+def _add_operations_to_graph(tape, graph, gate_types, q_mapper, c_mapper):
+    """Add the tape operation to the PyZX graph."""
+    # Create graph from circuit in the quantum tape (operations, measurements)
+    for op in tape.operations:
 
         # Check that the gate is compatible with PyZX
         name = op.name
         if name not in gate_types:
             raise qml.QuantumFunctionError(
-                "The expansion of the quantum script failed, PyZX does not support", name
+                "The expansion of the quantum tape failed, PyZX does not support", name
             )
 
         # Apply wires and parameters
@@ -366,7 +366,7 @@ def _add_operations_to_graph(qscript, graph, gate_types, q_mapper, c_mapper):
 
 
 def from_zx(graph, decompose_phases=True):
-    """Converts a graph from `PyZX <https://pyzx.readthedocs.io/en/latest/>`_ to a PennyLane qscript, if the graph is
+    """Converts a graph from `PyZX <https://pyzx.readthedocs.io/en/latest/>`_ to a PennyLane tape, if the graph is
     diagram-like.
 
     Args:
@@ -400,11 +400,11 @@ def from_zx(graph, decompose_phases=True):
         params = [5 / 4 * np.pi, 3 / 4 * np.pi, 0.1, 0.3]
         g = circuit(params)
 
-        pennylane_script = qml.transforms.from_zx(g)
+        pennylane_tape = qml.transforms.from_zx(g)
 
     You can check that the operations are similar but some were decomposed in the process.
 
-    >>> pennylane_script.operations
+    >>> pennylane_tape.operations
     [PauliZ(wires=[0]),
      T(wires=[0]),
      RX(0.1, wires=[1]),
@@ -503,8 +503,7 @@ def from_zx(graph, decompose_phases=True):
                     _add_two_qubit_gates(graph, vertex, neighbor, type_1, type_2, qubit_1, qubit_2)
                 )
 
-    qscript = QuantumScript(operations)
-    return qscript
+    return QuantumScript(operations)
 
 
 def _add_one_qubit_gate(param, type_1, qubit_1, decompose_phases):


Test patch:
diff --git a/pennylane/devices/tests/test_measurements.py b/pennylane/devices/tests/test_measurements.py
old mode 100755
new mode 100644
index f06caa39e..8a4eb4c69
--- a/pennylane/devices/tests/test_measurements.py
+++ b/pennylane/devices/tests/test_measurements.py
@@ -1627,7 +1627,7 @@ class TestCustomMeasurement:
         class MyMeasurement(MeasurementTransform):
             """Dummy measurement transform."""
 
-            def process(self, qscript, device):
+            def process(self, tape, device):
                 return 1
 
         @qml.qnode(dev)
@@ -1653,6 +1653,6 @@ class TestCustomMeasurement:
             return qml.classical_shadow(wires=0)
 
         circuit.device.measurement_map[ClassicalShadowMP] = "test_method"
-        circuit.device.test_method = lambda qscript: 2
+        circuit.device.test_method = lambda tape: 2
 
         assert circuit() == 2
diff --git a/tests/measurements/test_measurements.py b/tests/measurements/test_measurements.py
index b1464e106..6973ba215 100644
--- a/tests/measurements/test_measurements.py
+++ b/tests/measurements/test_measurements.py
@@ -564,8 +564,8 @@ class TestMeasurementTransform:
         switch_return()
 
         class MyMeasurement(MeasurementTransform):
-            def process(self, qscript, device):
-                return {device.shots: len(qscript)}
+            def process(self, tape, device):
+                return {device.shots: len(tape)}
 
         dev = qml.device("default.qubit", wires=2, shots=1000)
 
@@ -586,6 +586,6 @@ class TestMeasurementTransform:
             return qml.classical_shadow(wires=0)
 
         circuit.device.measurement_map[ClassicalShadowMP] = "test_method"
-        circuit.device.test_method = lambda qscript: 2
+        circuit.device.test_method = lambda tape: 2
 
         assert circuit() == 2
diff --git a/tests/transforms/test_zx.py b/tests/transforms/test_zx.py
index e4f90711e..3e40a3de4 100644
--- a/tests/transforms/test_zx.py
+++ b/tests/transforms/test_zx.py
@@ -487,7 +487,7 @@ class TestConvertersZX:
         qscript = QuantumScript(operations, [], [])
         with pytest.raises(
             qml.QuantumFunctionError,
-            match="The expansion of the quantum script failed, PyZX does not support",
+            match="The expansion of the quantum tape failed, PyZX does not support",
         ):
             qml.transforms.to_zx(qscript)