Jelly, 17 bytes
FAṀŒRṗLƲṁ€ðæ*2iị⁸
It's been over a week, so I figured I'd reveal my brute-force Jelly approach. This makes the following assumption, which I haven't managed to prove, but can't find a counter example:
Let \$B\$ be the input \$n \times n\$ matrix, and \$A\$ be an \$n \times n\$ matrix such that \$A^2 = B\$
Let \$b = \max\{|B_{ij}|, 1 \le i,j \le n\}\$ i.e. the largest absolute element of \$B\$. This answer assumes that, assuming \$A\$ exists, there is at least one matrix \$A\$ such that all its elements are in the inclusive range \$[-b, b]\$
For example, for $$B = \left[ \begin{matrix} 9 & -8 \\ 0 & 1 \end{matrix} \right]$$,$$B = \left[ \begin{matrix} 9 & -8 \\ 0 & 1 \end{matrix} \right],$$ \$b = 9\$ and there exists at least one \$A\$ such that all elements are between \$-9\$ and \$9\$ (the example in the question, for example)
How it works
FAṀŒRṗLƲṁ€ðæ*2iị⁸ - Main link. Takes B on the left
F - Flatten B
A - Absolute values of each.
Ʋ - Last 4 links as a monad f(abs(flat(B)):
Ṁ - Maximum
ŒR - Bounced range; [-max, +max]
L - Length i.e. number of elements of B
ṗ - Powerset
€ - Over each list:
ṁ - Mold it like B
Call this list of matrices M
ð - Begin a new dyadic chain with M on the left and B on the right
æ*2 - Matrix square of each matrix in M
i - Index of B in M
⁸ - Yield M
ị - Index back into M
One byte longer is a slightly more conventional way of extracting the root:
FAṀŒRṗLƲṁ€æ*2⁼ɗƇ⁸Ḣ
Here, the dyadic filter æ*2⁼ɗƇ
means that it would save a byte over the dyadic chaining with the indexing. However, as we should only output one solution, and the Ḣ
would chain to the filter without either ⁸
or ¹
, the indexing here actually saves a byte.