You've got a lot of pointers here. Take a deep breath.
*(*(parr + 2)) says, "take the second element of parr, and dereference it". This is equivalent to *parr[2].
*(*parr + 2) says, "take the first pointer pointed to by parr, add 2 to it, and dereference". It is equivalent to *(parr[0] + 2).
This all works because parr isn't a simple pointer to int (which is the type of pointer we usually use to access arrays of int), but rather, an array of three pointers to int. The situation looks like this:
+-----+-----+-----+
arr: | 1 | 2 | 3 |
+-----+-----+-----+
^ ^ ^
| | |
+--|--+--|--+--|--+
parr: | * | * | * |
+-----+-----+-----+
So it's easy to see how *parr[2] works; it just chases the third pointer in parr.
To see how the other expression works, let's first throw an ordinary pointer-to-int into the mix. Let's write
int *ip = arr;
(This is, as I said earlier, "the type of pointer we usually use to access arrays of int".) This gives us
+-----+-----+-----+
arr: | 1 | 2 | 3 |
+-----+-----+-----+
^
|
+--|--+
ip: | * |
+-----+
Now, it's a hallmark of C that a pointer-to-int accesses an array-of-int perfectly, just as well as the original array did. (Actually this is true for any pointer-to-T and array-of-T.) p points to a[0], but by pointer arithmetic, p+1 points to a[1], and p+2 points to a[2].
In fact, when we say *p, that's actually p[0], which is actually a[0]. When we say *(p+1), that's actually p[1], which is actually a[1]. When we say *(p+2), that's actually p[2], which is actually a[2]. Etc.
But the ip I defined is the same pointer as your parr[0]. So *(*parr + 2) is *(ip + 2) which is a[2].
Now, I blew past something which it sounds like you haven't really learned yet. I said,
It's a hallmark of C that a pointer-to-int accesses an array-of-int perfectly, just as well as the original array did.
By definition, when I have a pointer-to-type-T, and I add 1 to that pointer, the compiler makes it point to the next element in a conceptual array of T. So under the hood, the compiler doesn't add 1 to the address, it actually adds sizeof(T) to the address. For a pointer to int, on a 32-bit machine, that means adding 4, as you saw.
How does the compiler know how to do this? Well, this is the reason that pointers have types, the reason that they know what type they point to. When we declare
int *ip;
we are not just declaring ip to be a pointer; we are very specifically declaring it to be a pointer to int. So the compiler always knows it points to ints, so it always knows to multiply by 4 when doing pointer addition (and to divide by 4 when doing pointer subtraction, but that's another story).
And if this was your question, you need to skip to the chapter in your C book that talks about pointer arithmetic in C, and the special relationship between pointers and arrays. There are zillions of questions and answers here on Stack Overflow discussing that relationship, but I'm not sure which is the canonical one, so just now I can't point you at one.