code: def adjoint_cat(
      adj_sum_op, adj_prod_op, out_adj, name, parts, part_name
  ):
      if part_name not in out_adj.inputs:
          return tuple((part, out_adj) for part in parts)
      in_adjs = []
      start = 0
      size = sum(part.inputs[part_name].dtype for part in parts)
      for i, part in enumerate(parts):
          part_slice = Slice(
              name, start, start + part.inputs[part_name].dtype, 1, size
          )
          part_adj = out_adj(**{name: part_slice})
          in_adjs.append((part, part_adj))
          start += part.inputs[part_name].dtype
      return tuple(in_adjs)
  
imports: from collections import defaultdict
  from collections.abc import Hashable
  from funsor.cnf import Contraction
  from funsor.interpretations import Interpretation, reflect
  from funsor.interpreter import stack_reinterpret
  from funsor.ops import AssociativeOp
  from funsor.registry import KeyedRegistry
  from funsor.terms import Approximate, Binary, Cat, Funsor, Reduce, Scatter, Slice, Subs, substitute, to_funsor
  from .None import instrument, interpreter, ops
label_desc: Use image node_id 10 for calling a global function with example usage: adjoint_cat(adj_sum_op, adj_prod_op, out_adj, name, parts, part_name) and returns: tuple, tuple