code: def _custom_decomp_context(custom_decomps):
      """A context manager for applying custom decompositions of operations."""
  
      # Creates an individual context
      @contextlib.contextmanager
      def _custom_decomposition(obj, fn):
          # Covers the case where the user passes a string to indicate the Operator
          if isinstance(obj, str):
              obj = getattr(qml, obj)
  
          original_decomp_method = obj.compute_decomposition
  
          try:
              # Explicitly set the new compute_decomposition method
              obj.compute_decomposition = staticmethod(fn)
              yield
  
          finally:
              obj.compute_decomposition = staticmethod(
                  original_decomp_method
              )
  
      # Loop through the decomposition dictionary and create all the contexts
      try:
          with contextlib.ExitStack() as stack:
              for obj, fn in custom_decomps.items():
                  # We enter a new context for each decomposition the user passes
                  stack.enter_context(_custom_decomposition(obj, fn))
  
              stack = stack.pop_all()
  
          yield
  
      finally:
          stack.close()
  
file_path: pennylane/pennylane/transforms/tape_expand.py
imports: import contextlib
  import pennylane
  from pennylane.operation import has_gen, gen_is_multi_term_hamiltonian, has_grad_method, has_nopar, has_unitary_gen, is_measurement, is_trainable, not_tape
label_desc: Use image node_id 4 for calling a global function with example usage: _custom_decomp_context(custom_decomps) without return types