class_docstr: ``IterGraph`` is used to perform cross-iteration optimization.
  
  ``IterGraph`` keeps track of the 3 graphs, self (the original graph), setup graph, and
  cleanup graph. The 3 graphs should be identical copies of a ``fx.Graph``.
  
  IterGraph subclass fx.Graph to override the necessary APIs that will be used
  when constructing a optimization, e.g., communication fusion. IterGraph also
  provides APIs that originally belong to fx.Node and all these APIs will have
  ``node_`` prefix. For example, ``IterGraph.node_prepend`` is the equivalence
  of ``fx.Node.prepend``. Note that all the optimizations must be constructed
  using these APIs.
code: def move_after(
      self, nodes: List[fx.Node], target_node: fx.Node
  ) -> None:
      for graph in self._all_graphs:
          actual_nodes = [
              self._lookup_node(node, graph) for node in nodes
          ]
          actual_target_node = self._lookup_node(target_node, graph)
          for actual_node in actual_nodes:
              assert actual_target_node is not None
              actual_target_node.append(actual_node)
              actual_target_node = actual_node
  
imports: import copy
  import inspect
  import logging
  from typing import Any, Callable, cast, Dict, List, Optional, Set, Tuple, Type
  import torch.nn
  from torch import fx
  from torch.distributed._spmd.graph_utils import clone_subgraph, get_output, is_leaf_subgraph
  from torch.distributed._spmd.partial_lower import partial_lower
  from torch.fx.graph import _PyTreeCodeGen, PythonCode
  from torch.fx.node import Argument
  from torch.profiler import record_function
  from torch.utils import _pytree
  from torch.utils._pytree import tree_flatten, tree_map, tree_map_only, tree_unflatten
label_desc: Use image node_id 11 for calling the IterGraph obj's underlying member method code with example usage: obj.move_after(nodes, target_node) without return types