digraph sample { 
  graph [rankdir=TD]; node [shape=record];
  op [label="{Operator| InferShape()=0\lRun()=0\l | map&#60;string, string[]&#62; inputs_\lmap&#60;string, string[]&#62; outputs_ \l AttributeMap attrs_\l}"]; 
  op_with_kern [label="{OpWithKernel | InferShape()=0\lRun()\l | map&#60;OpKernelKey,OpKernel&#62;kernels_ }"]
  op_kernel [label="{OpKernel | Compute()=0}"]
  op_kernel_key [label="{OpKernelKey| Place place\n...}"]

  op -> op_with_kern [dir=back, arrowtail=onormal]
  op_with_kern -> op_kernel [arrowhead=vee, label="contains many"]

  {
    rank=same;
    op_with_kern
    op_kernel
  }

  op_kernel -> op_kernel_key [style=invis]

  {
    rank=same;
    op_kernel
    op_kernel_key
  }

  op_with_kern -> op_kernel_key [arrowhead=vee, label ="\nas map key"]

  mul_op [label="MulOp"]
  op_with_kern -> mul_op [dir=back, arrowtail=onormal]
  mul_kernel [label="template &#60;typename Place&#62;\lclass MulOpKernel\l"]
  op_kernel -> mul_kernel [dir=back, arrowtail=onormal]
  mul_op -> mul_kernel [arrowhead=vee, label="register many"]
  
  {
    rank=same;
    mul_op;
    mul_kernel;
  }
}