Rotor Routers on a Grid
CJam, 62 61 63 bytes

Try it online

Nq_N#):D;+_,2/{:P"^&lt;v&gt;^

"_P4$=#:X)=t_,0PX[1DW*WDSP]=-e&gt;e&lt;}h;1&gt;


Expanded and commented:

Nq              "Read the input grid";
_N#):D;         "Calculate the vertical delta (line length + 1)";
+               "Prepend a newline to the grid";
_,2/            "Calculate the initial position as the length of the grid
                 string divided by 2";
{               "Do...";
  :P"^&lt;v&gt;^

"
  _P4$=           "Get the character indexed by the position in the grid";
  #:X             "Map the character to an operation number:
                   '^'=&gt;0, '&lt;'=&gt;1, 'v'=&gt;2, '&gt;'=&gt;3, '^'=&gt;4, '\n'=&gt;5, '\n'=&gt;6
                   (the unreachable duplicate mappings are important below)";
  )=t             "Set the character indexed by the position in the grid to
                   the result of mapping the operation number + 1 backwards";
  _,0PX[1DW*WDSP]="Map the operation number to a negated delta (this occurs
                   after rotating routers, which means that operation n should
                   act like the character corresponding to operation n + 1):
                   0=&gt;1, 1=&gt;-delta, 2=&gt;-1, 3=&gt;delta, 5=&gt;position";
  -e&gt;e&lt;           "Subtract the negated delta from the position and clamp it to
                   [0, length of the grid string] (array indices are circular,
                   so the length of the grid string will act like the index 0
                   and point to the initial newline next iteration, which will
                   *really* set the position to 0)";
}h              "... while the position is not 0 (i.e. not at the initial
                 newline)";
;1&gt;             "Clean up and remove the initial newline";


My solution operates on the input as a flat string, so there's only one position value to keep track of and virtually no pre/postprocessing; there are only 2 bytes of preprocessing to add newline to the beginning of the grid and 2 bytes of postprocessing to remove it from the output. But these 4 bytes are well worth the cost as they let me keep newlines in and "execute" them like routers, but they "rotate" into another newline and set the position to zero. And the main loop ends when the position becomes zero.