Each layer index corresponds to a shift/transpose of this CZ pattern:

        ●───●   ●   ●   ●───●   ●   ● . . .

        ●   ●   ●───●   ●   ●   ●───● . . .

        ●───●   ●   ●   ●───●   ●   ● . . .

        ●   ●   ●───●   ●   ●   ●───● . . .

        ●───●   ●   ●   ●───●   ●   ● . . .

        ●   ●   ●───●   ●   ●   ●───● . . .
        .   .   .   .   .   .   .   . .
        .   .   .   .   .   .   .   .   .
        .   .   .   .   .   .   .   .     .

    Labelled edges, showing the exact index-to-CZs mapping (mod 8):

         ●─0─●─2─●─4─●─6─●─0─. . .
        3│  7│  3│  7│  3│
         ●─4─●─6─●─0─●─2─●─4─. . .
        1│  5│  1│  5│  1│
         ●─0─●─2─●─4─●─6─●─0─. . .
        7│  3│  7│  3│  7│
         ●─4─●─6─●─0─●─2─●─4─. . .
        5│  1│  5│  1│  5│
         ●─0─●─2─●─4─●─6─●─0─. . .
        3│  7│  3│  7│  3│
         .   .   .   .   .   .
         .   .   .   .   .     .
         .   .   .   .   .       .

    Note that, for small devices, some layers will be empty because the layer
    only contains edges not present on the device.

def _make_cz_layer(qubits: Iterable[devices.GridQubit], layer_index: int
                   ) -> Iterable[ops.Operation]:
    """
    Each layer index corresponds to a shift/transpose of this CZ pattern:

        ●───●   ●   ●   ●───●   ●   ● . . .

        ●   ●   ●───●   ●   ●   ●───● . . .

        ●───●   ●   ●   ●───●   ●   ● . . .

        ●   ●   ●───●   ●   ●   ●───● . . .

        ●───●   ●   ●   ●───●   ●   ● . . .

        ●   ●   ●───●   ●   ●   ●───● . . .
        .   .   .   .   .   .   .   . .
        .   .   .   .   .   .   .   .   .
        .   .   .   .   .   .   .   .     .

    Labelled edges, showing the exact index-to-CZs mapping (mod 8):

         ●─0─●─2─●─4─●─6─●─0─. . .
        3│  7│  3│  7│  3│
         ●─4─●─6─●─0─●─2─●─4─. . .
        1│  5│  1│  5│  1│
         ●─0─●─2─●─4─●─6─●─0─. . .
        7│  3│  7│  3│  7│
         ●─4─●─6─●─0─●─2─●─4─. . .
        5│  1│  5│  1│  5│
         ●─0─●─2─●─4─●─6─●─0─. . .
        3│  7│  3│  7│  3│
         .   .   .   .   .   .
         .   .   .   .   .     .
         .   .   .   .   .       .

    Note that, for small devices, some layers will be empty because the layer
    only contains edges not present on the device.
    """

    # map to an internal layer index to match the cycle order of public circuits
    layer_index_map = [0, 3, 2, 1, 4, 7, 6, 5]
    internal_layer_index = layer_index_map[layer_index % 8]

    dir_row = internal_layer_index % 2
    dir_col = 1 - dir_row
    shift = (internal_layer_index >> 1) % 4

    for q in qubits:
        q2 = devices.GridQubit(q.row + dir_row, q.col + dir_col)
        if q2 not in qubits:
            continue  # This edge isn't on the device.
        if (q.row * (2 - dir_row) + q.col * (2 - dir_col)) % 4 != shift:
            continue  # No CZ along this edge for this layer.

        yield ops.common_gates.CZ(q, q2)