docs: def measure(*qubits: raw_types.Qid,
              key: Optional[str] = None,
              invert_mask: Tuple[bool, ...] = ()
              ) -> gate_operation.GateOperation:
      """Returns a single MeasurementGate applied to all the given qubits.
  
      The qubits are measured in the computational basis.
  
      Args:
          *qubits: The qubits that the measurement gate should measure.
          key: The string key of the measurement. If this is None, it defaults
              to a comma-separated list of the target qubits' str values.
          invert_mask: A list of Truthy or Falsey values indicating whether
              the corresponding qubits should be flipped. None indicates no
              inverting should be done.
  
      Returns:
          An operation targeting the given qubits with a measurement.
  
      Raises:
          ValueError if the qubits are not instances of Qid.
      """
      for qubit in qubits:
          if isinstance(qubit, np.ndarray):
              raise ValueError(
                      'measure() was called a numpy ndarray. Perhaps you meant '
                      'to call measure_state_vector on numpy array?'
              )
          elif not isinstance(qubit, raw_types.Qid):
              raise ValueError(
                      'measure() was called with type different than Qid.')
  
      if key is None:
          key = _default_measurement_key(qubits)
      return MeasurementGate(len(qubits), key, invert_mask).on(*qubits)