def METHOD_NAME(
    nncf_graph: NNCFGraph,
    shapeof_metatypes: List[OperatorMetatype],
    read_variable_metatypes: Optional[List[OperatorMetatype]] = None,
) -> NNCFGraph:
    """
    Removes the ShapeOf subgraphs from the provided NNCFGraph instance.
    :param nncf_graph: NNCFGraph instance for the transformation.
    :param shapeof_metatypes: List of backend-specific ShapeOf metatypes.
    :param read_variable_metatypes: List of backend-specific metatypes
        that also can be interpreted as inputs (ReadValue).
    :return: NNCFGraph without ShapeOf subgraphs.
    """
    read_variable_metatypes = read_variable_metatypes if read_variable_metatypes else []
    nodes_to_drop = set()
    shape_of_nodes = []
    infer_nodes = []
    similar_inputs = nncf_graph.get_nodes_by_metatypes(read_variable_metatypes)
    nodes_queue = collections.deque(nncf_graph.get_input_nodes() + similar_inputs)
    while nodes_queue:
        node = nodes_queue.pop()
        if node.metatype in shapeof_metatypes:
            shape_of_nodes.append(node)
            continue
        if node in infer_nodes:
            continue
        infer_nodes.append(node)
        nodes_queue.extend(nncf_graph.get_next_nodes(node))
    for shape_of_node in shape_of_nodes:
        nodes_to_drop.add(shape_of_node)
        shape_of_queue = collections.deque()
        shape_of_queue.extend(nncf_graph.get_next_nodes(shape_of_node))
        while shape_of_queue:
            node = shape_of_queue.pop()
            if node in nodes_to_drop or node in infer_nodes:
                continue
            nodes_to_drop.add(node)
            # traverse forward and backward to exclude full shape of subgraph
            # recursion excluded due to infer_nodes list around subgraph shape
            shape_of_queue.extend(nncf_graph.get_next_nodes(node) + nncf_graph.get_previous_nodes(node))
    nncf_graph.remove_nodes_from(nodes_to_drop)
    return nncf_graph